2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/param/param.h"
52 #include "auth/gensec/gensec.h"
53 #include "lib/util/string_wrappers.h"
54 #include "source3/lib/substitute.h"
56 #include <gnutls/gnutls.h>
57 #include <gnutls/crypto.h>
62 fstring host
, workgroup
, share
, password
, username
, myname
;
63 struct cli_credentials
*torture_creds
;
64 static const char *sockops
="TCP_NODELAY";
66 static int port_to_use
=0;
67 int torture_numops
=100;
68 int torture_blocksize
=1024*1024;
69 static int procnum
; /* records process count number when forking */
70 static struct cli_state
*current_cli
;
71 static fstring randomfname
;
72 static bool use_oplocks
;
73 static bool use_level_II_oplocks
;
74 static const char *client_txt
= "client_oplocks.txt";
75 static bool disable_spnego
;
76 static bool use_kerberos
;
77 static bool force_dos_errors
;
78 static fstring multishare_conn_fname
;
79 static bool use_multishare_conn
= False
;
80 static bool do_encrypt
;
81 static const char *local_path
= NULL
;
82 static enum smb_signing_setting signing_state
= SMB_SIGNING_DEFAULT
;
85 bool torture_showall
= False
;
87 static double create_procs(bool (*fn
)(int), bool *result
);
89 /********************************************************************
90 Ensure a connection is encrypted.
91 ********************************************************************/
93 static bool force_cli_encryption(struct cli_state
*c
,
94 const char *sharename
)
96 uint16_t major
, minor
;
97 uint32_t caplow
, caphigh
;
100 if (!SERVER_HAS_UNIX_CIFS(c
)) {
101 d_printf("Encryption required and "
102 "server that doesn't support "
103 "UNIX extensions - failing connect\n");
107 status
= cli_unix_extensions_version(c
, &major
, &minor
, &caplow
,
109 if (!NT_STATUS_IS_OK(status
)) {
110 d_printf("Encryption required and "
111 "can't get UNIX CIFS extensions "
112 "version from server: %s\n", nt_errstr(status
));
116 if (!(caplow
& CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
)) {
117 d_printf("Encryption required and "
118 "share %s doesn't support "
119 "encryption.\n", sharename
);
123 status
= cli_smb1_setup_encryption(c
, torture_creds
);
124 if (!NT_STATUS_IS_OK(status
)) {
125 d_printf("Encryption required and "
126 "setup failed with error %s.\n",
135 static struct cli_state
*open_nbt_connection(void)
141 if (disable_spnego
) {
142 flags
|= CLI_FULL_CONNECTION_DONT_SPNEGO
;
146 flags
|= CLI_FULL_CONNECTION_OPLOCKS
;
149 if (use_level_II_oplocks
) {
150 flags
|= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS
;
153 if (force_dos_errors
) {
154 flags
|= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS
;
157 status
= cli_connect_nb(host
, NULL
, port_to_use
, 0x20, myname
,
158 signing_state
, flags
, &c
);
159 if (!NT_STATUS_IS_OK(status
)) {
160 printf("Failed to connect with %s. Error %s\n", host
, nt_errstr(status
) );
164 cli_set_timeout(c
, 120000); /* set a really long timeout (2 minutes) */
169 /****************************************************************************
170 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
171 ****************************************************************************/
173 static bool cli_bad_session_request(int fd
,
174 struct nmb_name
*calling
, struct nmb_name
*called
)
183 uint8_t message_type
;
185 struct tevent_context
*ev
;
186 struct tevent_req
*req
;
188 frame
= talloc_stackframe();
190 iov
[0].iov_base
= len_buf
;
191 iov
[0].iov_len
= sizeof(len_buf
);
193 /* put in the destination name */
195 iov
[1].iov_base
= name_mangle(talloc_tos(), called
->name
,
197 if (iov
[1].iov_base
== NULL
) {
200 iov
[1].iov_len
= name_len((unsigned char *)iov
[1].iov_base
,
201 talloc_get_size(iov
[1].iov_base
));
205 iov
[2].iov_base
= name_mangle(talloc_tos(), calling
->name
,
207 if (iov
[2].iov_base
== NULL
) {
210 iov
[2].iov_len
= name_len((unsigned char *)iov
[2].iov_base
,
211 talloc_get_size(iov
[2].iov_base
));
213 /* Deliberately corrupt the name len (first byte) */
214 *((uint8_t *)iov
[2].iov_base
) = 100;
216 /* send a session request (RFC 1002) */
217 /* setup the packet length
218 * Remove four bytes from the length count, since the length
219 * field in the NBT Session Service header counts the number
220 * of bytes which follow. The cli_send_smb() function knows
221 * about this and accounts for those four bytes.
225 _smb_setlen(len_buf
, iov
[1].iov_len
+ iov
[2].iov_len
);
226 SCVAL(len_buf
,0,0x81);
228 len
= write_data_iov(fd
, iov
, 3);
233 ev
= samba_tevent_context_init(frame
);
237 req
= read_smb_send(frame
, ev
, fd
);
241 if (!tevent_req_poll(req
, ev
)) {
244 len
= read_smb_recv(req
, talloc_tos(), &inbuf
, &err
);
251 message_type
= CVAL(inbuf
, 0);
252 if (message_type
!= 0x83) {
253 d_fprintf(stderr
, "Expected msg type 0x83, got 0x%2.2x\n",
258 if (smb_len(inbuf
) != 1) {
259 d_fprintf(stderr
, "Expected smb_len 1, got %d\n",
260 (int)smb_len(inbuf
));
264 error
= CVAL(inbuf
, 4);
266 d_fprintf(stderr
, "Expected error 0x82, got %d\n",
277 /* Insert a NULL at the first separator of the given path and return a pointer
278 * to the remainder of the string.
281 terminate_path_at_separator(char * path
)
289 if ((p
= strchr_m(path
, '/'))) {
294 if ((p
= strchr_m(path
, '\\'))) {
304 parse a //server/share type UNC name
306 bool smbcli_parse_unc(const char *unc_name
, TALLOC_CTX
*mem_ctx
,
307 char **hostname
, char **sharename
)
311 *hostname
= *sharename
= NULL
;
313 if (strncmp(unc_name
, "\\\\", 2) &&
314 strncmp(unc_name
, "//", 2)) {
318 *hostname
= talloc_strdup(mem_ctx
, &unc_name
[2]);
319 p
= terminate_path_at_separator(*hostname
);
322 *sharename
= talloc_strdup(mem_ctx
, p
);
323 terminate_path_at_separator(*sharename
);
326 if (*hostname
&& *sharename
) {
330 TALLOC_FREE(*hostname
);
331 TALLOC_FREE(*sharename
);
335 static bool torture_open_connection_share(struct cli_state
**c
,
336 const char *hostname
,
337 const char *sharename
,
342 status
= cli_full_connection_creds(c
,
351 if (!NT_STATUS_IS_OK(status
)) {
352 printf("failed to open share connection: //%s/%s port:%d - %s\n",
353 hostname
, sharename
, port_to_use
, nt_errstr(status
));
357 cli_set_timeout(*c
, 120000); /* set a really long timeout (2 minutes) */
360 return force_cli_encryption(*c
,
366 bool torture_open_connection_flags(struct cli_state
**c
, int conn_index
, int flags
)
368 char **unc_list
= NULL
;
369 int num_unc_names
= 0;
372 if (use_multishare_conn
==True
) {
374 unc_list
= file_lines_load(multishare_conn_fname
, &num_unc_names
, 0, NULL
);
375 if (!unc_list
|| num_unc_names
<= 0) {
376 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname
);
380 if (!smbcli_parse_unc(unc_list
[conn_index
% num_unc_names
],
382 printf("Failed to parse UNC name %s\n",
383 unc_list
[conn_index
% num_unc_names
]);
384 TALLOC_FREE(unc_list
);
388 result
= torture_open_connection_share(c
, h
, s
, flags
);
390 /* h, s were copied earlier */
391 TALLOC_FREE(unc_list
);
395 return torture_open_connection_share(c
, host
, share
, flags
);
398 bool torture_open_connection(struct cli_state
**c
, int conn_index
)
400 int flags
= CLI_FULL_CONNECTION_FORCE_SMB1
;
403 flags
|= CLI_FULL_CONNECTION_OPLOCKS
;
405 if (use_level_II_oplocks
) {
406 flags
|= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS
;
409 return torture_open_connection_flags(c
, conn_index
, flags
);
412 bool torture_init_connection(struct cli_state
**pcli
)
414 struct cli_state
*cli
;
416 cli
= open_nbt_connection();
425 bool torture_cli_session_setup2(struct cli_state
*cli
, uint16_t *new_vuid
)
427 uint16_t old_vuid
= cli_state_get_uid(cli
);
431 cli_state_set_uid(cli
, 0);
432 status
= cli_session_setup_creds(cli
, torture_creds
);
433 ret
= NT_STATUS_IS_OK(status
);
434 *new_vuid
= cli_state_get_uid(cli
);
435 cli_state_set_uid(cli
, old_vuid
);
440 bool torture_close_connection(struct cli_state
*c
)
445 status
= cli_tdis(c
);
446 if (!NT_STATUS_IS_OK(status
)) {
447 printf("tdis failed (%s)\n", nt_errstr(status
));
456 void torture_conn_set_sockopt(struct cli_state
*cli
)
458 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
461 static NTSTATUS
torture_delete_fn(struct file_info
*finfo
,
466 char *filename
= NULL
;
467 char *dirname
= NULL
;
469 TALLOC_CTX
*frame
= talloc_stackframe();
470 struct cli_state
*cli
= (struct cli_state
*)state
;
472 if (ISDOT(finfo
->name
) || ISDOTDOT(finfo
->name
)) {
477 dirname
= talloc_strdup(frame
, pattern
);
478 if (dirname
== NULL
) {
480 return NT_STATUS_NO_MEMORY
;
482 p
= strrchr_m(dirname
, '\\');
484 /* Remove the terminating '\' */
487 if (dirname
[0] != '\0') {
488 filename
= talloc_asprintf(frame
,
493 filename
= talloc_asprintf(frame
,
497 if (filename
== NULL
) {
499 return NT_STATUS_NO_MEMORY
;
501 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
502 char *subdirname
= talloc_asprintf(frame
,
505 if (subdirname
== NULL
) {
507 return NT_STATUS_NO_MEMORY
;
509 status
= cli_list(cli
,
511 FILE_ATTRIBUTE_DIRECTORY
|
512 FILE_ATTRIBUTE_HIDDEN
|
513 FILE_ATTRIBUTE_SYSTEM
,
516 if (!NT_STATUS_IS_OK(status
)) {
517 printf("torture_delete_fn: cli_list "
518 "of %s failed (%s)\n",
524 status
= cli_rmdir(cli
, filename
);
526 status
= cli_unlink(cli
,
528 FILE_ATTRIBUTE_SYSTEM
|
529 FILE_ATTRIBUTE_HIDDEN
);
531 if (!NT_STATUS_IS_OK(status
)) {
532 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
533 printf("torture_delete_fn: cli_rmdir"
534 " of %s failed (%s)\n",
538 printf("torture_delete_fn: cli_unlink"
539 " of %s failed (%s)\n",
548 void torture_deltree(struct cli_state
*cli
, const char *dname
)
553 /* It might be a file */
554 (void)cli_unlink(cli
,
556 FILE_ATTRIBUTE_SYSTEM
|
557 FILE_ATTRIBUTE_HIDDEN
);
559 mask
= talloc_asprintf(cli
,
563 printf("torture_deltree: talloc_asprintf failed\n");
567 status
= cli_list(cli
,
569 FILE_ATTRIBUTE_DIRECTORY
|
570 FILE_ATTRIBUTE_HIDDEN
|
571 FILE_ATTRIBUTE_SYSTEM
,
574 if (!NT_STATUS_IS_OK(status
)) {
575 printf("torture_deltree: cli_list of %s failed (%s)\n",
580 status
= cli_rmdir(cli
, dname
);
581 if (!NT_STATUS_IS_OK(status
)) {
582 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
588 /* check if the server produced the expected dos or nt error code */
589 static bool check_both_error(int line
, NTSTATUS status
,
590 uint8_t eclass
, uint32_t ecode
, NTSTATUS nterr
)
592 if (NT_STATUS_IS_DOS(status
)) {
596 /* Check DOS error */
597 cclass
= NT_STATUS_DOS_CLASS(status
);
598 num
= NT_STATUS_DOS_CODE(status
);
600 if (eclass
!= cclass
|| ecode
!= num
) {
601 printf("unexpected error code class=%d code=%d\n",
602 (int)cclass
, (int)num
);
603 printf(" expected %d/%d %s (line=%d)\n",
604 (int)eclass
, (int)ecode
, nt_errstr(nterr
), line
);
609 if (!NT_STATUS_EQUAL(nterr
, status
)) {
610 printf("unexpected error code %s\n",
612 printf(" expected %s (line=%d)\n",
613 nt_errstr(nterr
), line
);
622 /* check if the server produced the expected error code */
623 static bool check_error(int line
, NTSTATUS status
,
624 uint8_t eclass
, uint32_t ecode
, NTSTATUS nterr
)
626 if (NT_STATUS_IS_DOS(status
)) {
630 /* Check DOS error */
632 cclass
= NT_STATUS_DOS_CLASS(status
);
633 num
= NT_STATUS_DOS_CODE(status
);
635 if (eclass
!= cclass
|| ecode
!= num
) {
636 printf("unexpected error code class=%d code=%d\n",
637 (int)cclass
, (int)num
);
638 printf(" expected %d/%d %s (line=%d)\n",
639 (int)eclass
, (int)ecode
, nt_errstr(nterr
),
647 if (NT_STATUS_V(nterr
) != NT_STATUS_V(status
)) {
648 printf("unexpected error code %s\n",
650 printf(" expected %s (line=%d)\n", nt_errstr(nterr
),
660 static bool wait_lock(struct cli_state
*c
, int fnum
, uint32_t offset
, uint32_t len
)
664 status
= cli_lock32(c
, fnum
, offset
, len
, -1, WRITE_LOCK
);
666 while (!NT_STATUS_IS_OK(status
)) {
667 if (!check_both_error(__LINE__
, status
, ERRDOS
,
668 ERRlock
, NT_STATUS_LOCK_NOT_GRANTED
)) {
672 status
= cli_lock32(c
, fnum
, offset
, len
, -1, WRITE_LOCK
);
679 static bool rw_torture(struct cli_state
*c
)
681 const char *lockfname
= "\\torture.lck";
685 pid_t pid2
, pid
= getpid();
692 memset(buf
, '\0', sizeof(buf
));
694 status
= cli_openx(c
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
696 if (!NT_STATUS_IS_OK(status
)) {
697 status
= cli_openx(c
, lockfname
, O_RDWR
, DENY_NONE
, &fnum2
);
699 if (!NT_STATUS_IS_OK(status
)) {
700 printf("open of %s failed (%s)\n",
701 lockfname
, nt_errstr(status
));
705 for (i
=0;i
<torture_numops
;i
++) {
706 unsigned n
= (unsigned)sys_random()%10;
709 printf("%d\r", i
); fflush(stdout
);
711 slprintf(fname
, sizeof(fstring
) - 1, "\\torture.%u", n
);
713 if (!wait_lock(c
, fnum2
, n
*sizeof(int), sizeof(int))) {
717 status
= cli_openx(c
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
,
719 if (!NT_STATUS_IS_OK(status
)) {
720 printf("open failed (%s)\n", nt_errstr(status
));
725 status
= cli_writeall(c
, fnum
, 0, (uint8_t *)&pid
, 0,
727 if (!NT_STATUS_IS_OK(status
)) {
728 printf("write failed (%s)\n", nt_errstr(status
));
733 status
= cli_writeall(c
, fnum
, 0, (uint8_t *)buf
,
734 sizeof(pid
)+(j
*sizeof(buf
)),
736 if (!NT_STATUS_IS_OK(status
)) {
737 printf("write failed (%s)\n",
745 status
= cli_read(c
, fnum
, (char *)&pid2
, 0, sizeof(pid
),
747 if (!NT_STATUS_IS_OK(status
)) {
748 printf("read failed (%s)\n", nt_errstr(status
));
750 } else if (nread
!= sizeof(pid
)) {
751 printf("read/write compare failed: "
752 "recv %ld req %ld\n", (unsigned long)nread
,
753 (unsigned long)sizeof(pid
));
758 printf("data corruption!\n");
762 status
= cli_close(c
, fnum
);
763 if (!NT_STATUS_IS_OK(status
)) {
764 printf("close failed (%s)\n", nt_errstr(status
));
768 status
= cli_unlink(c
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
769 if (!NT_STATUS_IS_OK(status
)) {
770 printf("unlink failed (%s)\n", nt_errstr(status
));
774 status
= cli_unlock(c
, fnum2
, n
*sizeof(int), sizeof(int));
775 if (!NT_STATUS_IS_OK(status
)) {
776 printf("unlock failed (%s)\n", nt_errstr(status
));
782 cli_unlink(c
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
789 static bool run_torture(int dummy
)
791 struct cli_state
*cli
;
796 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
798 ret
= rw_torture(cli
);
800 if (!torture_close_connection(cli
)) {
807 static bool rw_torture3(struct cli_state
*c
, char *lockfname
)
809 uint16_t fnum
= (uint16_t)-1;
814 unsigned countprev
= 0;
817 NTSTATUS status
= NT_STATUS_OK
;
820 for (i
= 0; i
< sizeof(buf
); i
+= sizeof(uint32_t))
822 SIVAL(buf
, i
, sys_random());
829 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
830 if (!NT_STATUS_IS_OK(status
)) {
831 printf("unlink failed (%s) (normal, this file should "
832 "not exist)\n", nt_errstr(status
));
835 status
= cli_openx(c
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
837 if (!NT_STATUS_IS_OK(status
)) {
838 printf("first open read/write of %s failed (%s)\n",
839 lockfname
, nt_errstr(status
));
845 for (i
= 0; i
< 500 && fnum
== (uint16_t)-1; i
++)
847 status
= cli_openx(c
, lockfname
, O_RDONLY
,
849 if (NT_STATUS_IS_OK(status
)) {
854 if (!NT_STATUS_IS_OK(status
)) {
855 printf("second open read-only of %s failed (%s)\n",
856 lockfname
, nt_errstr(status
));
862 for (count
= 0; count
< sizeof(buf
); count
+= sent
)
864 if (count
>= countprev
) {
865 printf("%d %8d\r", i
, count
);
868 countprev
+= (sizeof(buf
) / 20);
873 sent
= ((unsigned)sys_random()%(20))+ 1;
874 if (sent
> sizeof(buf
) - count
)
876 sent
= sizeof(buf
) - count
;
879 status
= cli_writeall(c
, fnum
, 0, (uint8_t *)buf
+count
,
881 if (!NT_STATUS_IS_OK(status
)) {
882 printf("write failed (%s)\n",
889 status
= cli_read(c
, fnum
, buf_rd
+count
, count
,
890 sizeof(buf
)-count
, &sent
);
891 if(!NT_STATUS_IS_OK(status
)) {
892 printf("read failed offset:%d size:%ld (%s)\n",
893 count
, (unsigned long)sizeof(buf
)-count
,
897 } else if (sent
> 0) {
898 if (memcmp(buf_rd
+count
, buf
+count
, sent
) != 0)
900 printf("read/write compare failed\n");
901 printf("offset: %d req %ld recvd %ld\n", count
, (unsigned long)sizeof(buf
)-count
, (unsigned long)sent
);
910 status
= cli_close(c
, fnum
);
911 if (!NT_STATUS_IS_OK(status
)) {
912 printf("close failed (%s)\n", nt_errstr(status
));
919 static bool rw_torture2(struct cli_state
*c1
, struct cli_state
*c2
)
921 const char *lockfname
= "\\torture2.lck";
931 status
= cli_unlink(c1
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
932 if (!NT_STATUS_IS_OK(status
)) {
933 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status
));
936 status
= cli_openx(c1
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
938 if (!NT_STATUS_IS_OK(status
)) {
939 printf("first open read/write of %s failed (%s)\n",
940 lockfname
, nt_errstr(status
));
944 status
= cli_openx(c2
, lockfname
, O_RDONLY
, DENY_NONE
, &fnum2
);
945 if (!NT_STATUS_IS_OK(status
)) {
946 printf("second open read-only of %s failed (%s)\n",
947 lockfname
, nt_errstr(status
));
948 cli_close(c1
, fnum1
);
952 for (i
= 0; i
< torture_numops
; i
++)
954 size_t buf_size
= ((unsigned)sys_random()%(sizeof(buf
)-1))+ 1;
956 printf("%d\r", i
); fflush(stdout
);
959 generate_random_buffer((unsigned char *)buf
, buf_size
);
961 status
= cli_writeall(c1
, fnum1
, 0, (uint8_t *)buf
, 0,
963 if (!NT_STATUS_IS_OK(status
)) {
964 printf("write failed (%s)\n", nt_errstr(status
));
969 status
= cli_read(c2
, fnum2
, buf_rd
, 0, buf_size
, &bytes_read
);
970 if(!NT_STATUS_IS_OK(status
)) {
971 printf("read failed (%s)\n", nt_errstr(status
));
974 } else if (bytes_read
!= buf_size
) {
975 printf("read failed\n");
976 printf("read %ld, expected %ld\n",
977 (unsigned long)bytes_read
,
978 (unsigned long)buf_size
);
983 if (memcmp(buf_rd
, buf
, buf_size
) != 0)
985 printf("read/write compare failed\n");
991 status
= cli_close(c2
, fnum2
);
992 if (!NT_STATUS_IS_OK(status
)) {
993 printf("close failed (%s)\n", nt_errstr(status
));
997 status
= cli_close(c1
, fnum1
);
998 if (!NT_STATUS_IS_OK(status
)) {
999 printf("close failed (%s)\n", nt_errstr(status
));
1003 status
= cli_unlink(c1
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1004 if (!NT_STATUS_IS_OK(status
)) {
1005 printf("unlink failed (%s)\n", nt_errstr(status
));
1012 static bool run_readwritetest(int dummy
)
1014 struct cli_state
*cli1
, *cli2
;
1015 bool test1
, test2
= False
;
1017 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
1020 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
1021 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
1023 printf("starting readwritetest\n");
1025 test1
= rw_torture2(cli1
, cli2
);
1026 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1
));
1029 test2
= rw_torture2(cli1
, cli1
);
1030 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2
));
1033 if (!torture_close_connection(cli1
)) {
1037 if (!torture_close_connection(cli2
)) {
1041 return (test1
&& test2
);
1044 static bool run_readwritemulti(int dummy
)
1046 struct cli_state
*cli
;
1051 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1053 printf("run_readwritemulti: fname %s\n", randomfname
);
1054 test
= rw_torture3(cli
, randomfname
);
1056 if (!torture_close_connection(cli
)) {
1063 static bool run_readwritelarge_internal(void)
1065 static struct cli_state
*cli1
;
1067 const char *lockfname
= "\\large.dat";
1070 bool correct
= True
;
1073 if (!torture_open_connection(&cli1
, 0)) {
1076 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
1077 memset(buf
,'\0',sizeof(buf
));
1079 printf("starting readwritelarge_internal\n");
1081 cli_unlink(cli1
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1083 status
= cli_openx(cli1
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
1085 if (!NT_STATUS_IS_OK(status
)) {
1086 printf("open read/write of %s failed (%s)\n", lockfname
, nt_errstr(status
));
1090 cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, sizeof(buf
), NULL
);
1092 status
= cli_qfileinfo_basic(cli1
, fnum1
, NULL
, &fsize
, NULL
, NULL
,
1094 if (!NT_STATUS_IS_OK(status
)) {
1095 printf("qfileinfo failed (%s)\n", nt_errstr(status
));
1099 if (fsize
== sizeof(buf
))
1100 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1101 (unsigned long)fsize
);
1103 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1104 (unsigned long)fsize
);
1108 status
= cli_close(cli1
, fnum1
);
1109 if (!NT_STATUS_IS_OK(status
)) {
1110 printf("close failed (%s)\n", nt_errstr(status
));
1114 status
= cli_unlink(cli1
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1115 if (!NT_STATUS_IS_OK(status
)) {
1116 printf("unlink failed (%s)\n", nt_errstr(status
));
1120 status
= cli_openx(cli1
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
1122 if (!NT_STATUS_IS_OK(status
)) {
1123 printf("open read/write of %s failed (%s)\n", lockfname
, nt_errstr(status
));
1127 cli_smbwrite(cli1
, fnum1
, buf
, 0, sizeof(buf
), NULL
);
1129 status
= cli_qfileinfo_basic(cli1
, fnum1
, NULL
, &fsize
, NULL
, NULL
,
1131 if (!NT_STATUS_IS_OK(status
)) {
1132 printf("qfileinfo failed (%s)\n", nt_errstr(status
));
1136 if (fsize
== sizeof(buf
))
1137 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1138 (unsigned long)fsize
);
1140 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1141 (unsigned long)fsize
);
1145 status
= cli_close(cli1
, fnum1
);
1146 if (!NT_STATUS_IS_OK(status
)) {
1147 printf("close failed (%s)\n", nt_errstr(status
));
1151 if (!torture_close_connection(cli1
)) {
1157 static bool run_readwritelarge(int dummy
)
1159 return run_readwritelarge_internal();
1162 static bool run_readwritelarge_signtest(int dummy
)
1165 signing_state
= SMB_SIGNING_REQUIRED
;
1166 ret
= run_readwritelarge_internal();
1167 signing_state
= SMB_SIGNING_DEFAULT
;
1174 #define ival(s) strtol(s, NULL, 0)
1176 /* run a test that simulates an approximate netbench client load */
1177 static bool run_netbench(int client
)
1179 struct cli_state
*cli
;
1184 const char *params
[20];
1185 bool correct
= True
;
1191 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1195 slprintf(cname
,sizeof(cname
)-1, "client%d", client
);
1197 f
= fopen(client_txt
, "r");
1204 while (fgets(line
, sizeof(line
)-1, f
)) {
1208 line
[strlen(line
)-1] = 0;
1210 /* printf("[%d] %s\n", line_count, line); */
1212 all_string_sub(line
,"client1", cname
, sizeof(line
));
1214 /* parse the command parameters */
1215 params
[0] = strtok_r(line
, " ", &saveptr
);
1217 while (params
[i
]) params
[++i
] = strtok_r(NULL
, " ", &saveptr
);
1221 if (i
< 2) continue;
1223 if (!strncmp(params
[0],"SMB", 3)) {
1224 printf("ERROR: You are using a dbench 1 load file\n");
1228 if (!strcmp(params
[0],"NTCreateX")) {
1229 nb_createx(params
[1], ival(params
[2]), ival(params
[3]),
1231 } else if (!strcmp(params
[0],"Close")) {
1232 nb_close(ival(params
[1]));
1233 } else if (!strcmp(params
[0],"Rename")) {
1234 nb_rename(params
[1], params
[2]);
1235 } else if (!strcmp(params
[0],"Unlink")) {
1236 nb_unlink(params
[1]);
1237 } else if (!strcmp(params
[0],"Deltree")) {
1238 nb_deltree(params
[1]);
1239 } else if (!strcmp(params
[0],"Rmdir")) {
1240 nb_rmdir(params
[1]);
1241 } else if (!strcmp(params
[0],"QUERY_PATH_INFORMATION")) {
1242 nb_qpathinfo(params
[1]);
1243 } else if (!strcmp(params
[0],"QUERY_FILE_INFORMATION")) {
1244 nb_qfileinfo(ival(params
[1]));
1245 } else if (!strcmp(params
[0],"QUERY_FS_INFORMATION")) {
1246 nb_qfsinfo(ival(params
[1]));
1247 } else if (!strcmp(params
[0],"FIND_FIRST")) {
1248 nb_findfirst(params
[1]);
1249 } else if (!strcmp(params
[0],"WriteX")) {
1250 nb_writex(ival(params
[1]),
1251 ival(params
[2]), ival(params
[3]), ival(params
[4]));
1252 } else if (!strcmp(params
[0],"ReadX")) {
1253 nb_readx(ival(params
[1]),
1254 ival(params
[2]), ival(params
[3]), ival(params
[4]));
1255 } else if (!strcmp(params
[0],"Flush")) {
1256 nb_flush(ival(params
[1]));
1258 printf("Unknown operation %s\n", params
[0]);
1266 if (!torture_close_connection(cli
)) {
1274 /* run a test that simulates an approximate netbench client load */
1275 static bool run_nbench(int dummy
)
1278 bool correct
= True
;
1280 nbio_shmem(torture_nprocs
);
1284 signal(SIGALRM
, nb_alarm
);
1286 t
= create_procs(run_netbench
, &correct
);
1289 printf("\nThroughput %g MB/sec\n",
1290 1.0e-6 * nbio_total() / t
);
1296 This test checks for two things:
1298 1) correct support for retaining locks over a close (ie. the server
1299 must not use posix semantics)
1300 2) support for lock timeouts
1302 static bool run_locktest1(int dummy
)
1304 struct cli_state
*cli1
, *cli2
;
1305 const char *fname
= "\\lockt1.lck";
1306 uint16_t fnum1
, fnum2
, fnum3
;
1308 unsigned lock_timeout
;
1311 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
1314 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
1315 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
1317 printf("starting locktest1\n");
1319 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1321 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
1323 if (!NT_STATUS_IS_OK(status
)) {
1324 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
1328 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
1329 if (!NT_STATUS_IS_OK(status
)) {
1330 printf("open2 of %s failed (%s)\n", fname
, nt_errstr(status
));
1334 status
= cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum3
);
1335 if (!NT_STATUS_IS_OK(status
)) {
1336 printf("open3 of %s failed (%s)\n", fname
, nt_errstr(status
));
1340 status
= cli_lock32(cli1
, fnum1
, 0, 4, 0, WRITE_LOCK
);
1341 if (!NT_STATUS_IS_OK(status
)) {
1342 printf("lock1 failed (%s)\n", nt_errstr(status
));
1346 status
= cli_lock32(cli2
, fnum3
, 0, 4, 0, WRITE_LOCK
);
1347 if (NT_STATUS_IS_OK(status
)) {
1348 printf("lock2 succeeded! This is a locking bug\n");
1351 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1352 NT_STATUS_LOCK_NOT_GRANTED
)) {
1357 lock_timeout
= (1 + (random() % 20));
1358 printf("Testing lock timeout with timeout=%u\n", lock_timeout
);
1360 status
= cli_lock32(cli2
, fnum3
, 0, 4, lock_timeout
* 1000, WRITE_LOCK
);
1361 if (NT_STATUS_IS_OK(status
)) {
1362 printf("lock3 succeeded! This is a locking bug\n");
1365 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1366 NT_STATUS_FILE_LOCK_CONFLICT
)) {
1372 if (ABS(t2
- t1
) < lock_timeout
-1) {
1373 printf("error: This server appears not to support timed lock requests\n");
1376 printf("server slept for %u seconds for a %u second timeout\n",
1377 (unsigned int)(t2
-t1
), lock_timeout
);
1379 status
= cli_close(cli1
, fnum2
);
1380 if (!NT_STATUS_IS_OK(status
)) {
1381 printf("close1 failed (%s)\n", nt_errstr(status
));
1385 status
= cli_lock32(cli2
, fnum3
, 0, 4, 0, WRITE_LOCK
);
1386 if (NT_STATUS_IS_OK(status
)) {
1387 printf("lock4 succeeded! This is a locking bug\n");
1390 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1391 NT_STATUS_FILE_LOCK_CONFLICT
)) {
1396 status
= cli_close(cli1
, fnum1
);
1397 if (!NT_STATUS_IS_OK(status
)) {
1398 printf("close2 failed (%s)\n", nt_errstr(status
));
1402 status
= cli_close(cli2
, fnum3
);
1403 if (!NT_STATUS_IS_OK(status
)) {
1404 printf("close3 failed (%s)\n", nt_errstr(status
));
1408 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1409 if (!NT_STATUS_IS_OK(status
)) {
1410 printf("unlink failed (%s)\n", nt_errstr(status
));
1415 if (!torture_close_connection(cli1
)) {
1419 if (!torture_close_connection(cli2
)) {
1423 printf("Passed locktest1\n");
1428 this checks to see if a secondary tconx can use open files from an
1431 static bool run_tcon_test(int dummy
)
1433 static struct cli_state
*cli
;
1434 const char *fname
= "\\tcontest.tmp";
1436 uint32_t cnum1
, cnum2
, cnum3
;
1437 struct smbXcli_tcon
*orig_tcon
= NULL
;
1438 char *orig_share
= NULL
;
1439 uint16_t vuid1
, vuid2
;
1444 memset(buf
, '\0', sizeof(buf
));
1446 if (!torture_open_connection(&cli
, 0)) {
1449 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1451 printf("starting tcontest\n");
1453 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1455 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
1456 if (!NT_STATUS_IS_OK(status
)) {
1457 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
1461 cnum1
= cli_state_get_tid(cli
);
1462 vuid1
= cli_state_get_uid(cli
);
1464 status
= cli_writeall(cli
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
1465 if (!NT_STATUS_IS_OK(status
)) {
1466 printf("initial write failed (%s)", nt_errstr(status
));
1470 cli_state_save_tcon_share(cli
, &orig_tcon
, &orig_share
);
1472 status
= cli_tree_connect_creds(cli
, share
, "?????", torture_creds
);
1473 if (!NT_STATUS_IS_OK(status
)) {
1474 printf("%s refused 2nd tree connect (%s)\n", host
,
1476 cli_state_restore_tcon_share(cli
, orig_tcon
, orig_share
);
1481 cnum2
= cli_state_get_tid(cli
);
1482 cnum3
= MAX(cnum1
, cnum2
) + 1; /* any invalid number */
1483 vuid2
= cli_state_get_uid(cli
) + 1;
1485 /* try a write with the wrong tid */
1486 cli_state_set_tid(cli
, cnum2
);
1488 status
= cli_writeall(cli
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
1489 if (NT_STATUS_IS_OK(status
)) {
1490 printf("* server allows write with wrong TID\n");
1493 printf("server fails write with wrong TID : %s\n",
1498 /* try a write with an invalid tid */
1499 cli_state_set_tid(cli
, cnum3
);
1501 status
= cli_writeall(cli
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
1502 if (NT_STATUS_IS_OK(status
)) {
1503 printf("* server allows write with invalid TID\n");
1506 printf("server fails write with invalid TID : %s\n",
1510 /* try a write with an invalid vuid */
1511 cli_state_set_uid(cli
, vuid2
);
1512 cli_state_set_tid(cli
, cnum1
);
1514 status
= cli_writeall(cli
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
1515 if (NT_STATUS_IS_OK(status
)) {
1516 printf("* server allows write with invalid VUID\n");
1519 printf("server fails write with invalid VUID : %s\n",
1523 cli_state_set_tid(cli
, cnum1
);
1524 cli_state_set_uid(cli
, vuid1
);
1526 status
= cli_close(cli
, fnum1
);
1527 if (!NT_STATUS_IS_OK(status
)) {
1528 printf("close failed (%s)\n", nt_errstr(status
));
1529 cli_state_restore_tcon_share(cli
, orig_tcon
, orig_share
);
1534 cli_state_set_tid(cli
, cnum2
);
1536 status
= cli_tdis(cli
);
1537 if (!NT_STATUS_IS_OK(status
)) {
1538 printf("secondary tdis failed (%s)\n", nt_errstr(status
));
1539 cli_state_restore_tcon_share(cli
, orig_tcon
, orig_share
);
1544 cli_state_restore_tcon_share(cli
, orig_tcon
, orig_share
);
1546 cli_state_set_tid(cli
, cnum1
);
1548 if (!torture_close_connection(cli
)) {
1557 checks for old style tcon support
1559 static bool run_tcon2_test(int dummy
)
1561 static struct cli_state
*cli
;
1562 uint16_t cnum
, max_xmit
;
1566 if (!torture_open_connection(&cli
, 0)) {
1569 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1571 printf("starting tcon2 test\n");
1573 if (asprintf(&service
, "\\\\%s\\%s", host
, share
) == -1) {
1577 status
= cli_raw_tcon(cli
, service
, password
, "?????", &max_xmit
, &cnum
);
1581 if (!NT_STATUS_IS_OK(status
)) {
1582 printf("tcon2 failed : %s\n", nt_errstr(status
));
1584 printf("tcon OK : max_xmit=%d cnum=%d\n",
1585 (int)max_xmit
, (int)cnum
);
1588 if (!torture_close_connection(cli
)) {
1592 printf("Passed tcon2 test\n");
1596 static bool tcon_devtest(struct cli_state
*cli
,
1597 const char *myshare
, const char *devtype
,
1598 const char *return_devtype
,
1599 NTSTATUS expected_error
)
1604 status
= cli_tree_connect_creds(cli
, myshare
, devtype
, torture_creds
);
1606 if (NT_STATUS_IS_OK(expected_error
)) {
1607 if (NT_STATUS_IS_OK(status
)) {
1608 if (return_devtype
!= NULL
&&
1609 strequal(cli
->dev
, return_devtype
)) {
1612 printf("tconX to share %s with type %s "
1613 "succeeded but returned the wrong "
1614 "device type (got [%s] but should have got [%s])\n",
1615 myshare
, devtype
, cli
->dev
, return_devtype
);
1619 printf("tconX to share %s with type %s "
1620 "should have succeeded but failed\n",
1626 if (NT_STATUS_IS_OK(status
)) {
1627 printf("tconx to share %s with type %s "
1628 "should have failed but succeeded\n",
1632 if (NT_STATUS_EQUAL(status
, expected_error
)) {
1635 printf("Returned unexpected error\n");
1644 checks for correct tconX support
1646 static bool run_tcon_devtype_test(int dummy
)
1648 static struct cli_state
*cli1
= NULL
;
1649 int flags
= CLI_FULL_CONNECTION_FORCE_SMB1
;
1653 status
= cli_full_connection_creds(&cli1
,
1659 NULL
, /* service_type */
1663 if (!NT_STATUS_IS_OK(status
)) {
1664 printf("could not open connection\n");
1668 if (!tcon_devtest(cli1
, "IPC$", "A:", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1671 if (!tcon_devtest(cli1
, "IPC$", "?????", "IPC", NT_STATUS_OK
))
1674 if (!tcon_devtest(cli1
, "IPC$", "LPT:", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1677 if (!tcon_devtest(cli1
, "IPC$", "IPC", "IPC", NT_STATUS_OK
))
1680 if (!tcon_devtest(cli1
, "IPC$", "FOOBA", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1683 if (!tcon_devtest(cli1
, share
, "A:", "A:", NT_STATUS_OK
))
1686 if (!tcon_devtest(cli1
, share
, "?????", "A:", NT_STATUS_OK
))
1689 if (!tcon_devtest(cli1
, share
, "LPT:", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1692 if (!tcon_devtest(cli1
, share
, "IPC", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1695 if (!tcon_devtest(cli1
, share
, "FOOBA", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1701 printf("Passed tcondevtest\n");
1708 This test checks that
1710 1) the server supports multiple locking contexts on the one SMB
1711 connection, distinguished by PID.
1713 2) the server correctly fails overlapping locks made by the same PID (this
1714 goes against POSIX behaviour, which is why it is tricky to implement)
1716 3) the server denies unlock requests by an incorrect client PID
1718 static bool run_locktest2(int dummy
)
1720 static struct cli_state
*cli
;
1721 const char *fname
= "\\lockt2.lck";
1722 uint16_t fnum1
, fnum2
, fnum3
;
1723 bool correct
= True
;
1726 if (!torture_open_connection(&cli
, 0)) {
1730 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1732 printf("starting locktest2\n");
1734 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1738 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
1739 if (!NT_STATUS_IS_OK(status
)) {
1740 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
1744 status
= cli_openx(cli
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
1745 if (!NT_STATUS_IS_OK(status
)) {
1746 printf("open2 of %s failed (%s)\n", fname
, nt_errstr(status
));
1752 status
= cli_openx(cli
, fname
, O_RDWR
, DENY_NONE
, &fnum3
);
1753 if (!NT_STATUS_IS_OK(status
)) {
1754 printf("open3 of %s failed (%s)\n", fname
, nt_errstr(status
));
1760 status
= cli_lock32(cli
, fnum1
, 0, 4, 0, WRITE_LOCK
);
1761 if (!NT_STATUS_IS_OK(status
)) {
1762 printf("lock1 failed (%s)\n", nt_errstr(status
));
1766 status
= cli_lock32(cli
, fnum1
, 0, 4, 0, WRITE_LOCK
);
1767 if (NT_STATUS_IS_OK(status
)) {
1768 printf("WRITE lock1 succeeded! This is a locking bug\n");
1771 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1772 NT_STATUS_LOCK_NOT_GRANTED
)) {
1777 status
= cli_lock32(cli
, fnum2
, 0, 4, 0, WRITE_LOCK
);
1778 if (NT_STATUS_IS_OK(status
)) {
1779 printf("WRITE lock2 succeeded! This is a locking bug\n");
1782 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1783 NT_STATUS_LOCK_NOT_GRANTED
)) {
1788 status
= cli_lock32(cli
, fnum2
, 0, 4, 0, READ_LOCK
);
1789 if (NT_STATUS_IS_OK(status
)) {
1790 printf("READ lock2 succeeded! This is a locking bug\n");
1793 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1794 NT_STATUS_FILE_LOCK_CONFLICT
)) {
1799 status
= cli_lock32(cli
, fnum1
, 100, 4, 0, WRITE_LOCK
);
1800 if (!NT_STATUS_IS_OK(status
)) {
1801 printf("lock at 100 failed (%s)\n", nt_errstr(status
));
1804 if (NT_STATUS_IS_OK(cli_unlock(cli
, fnum1
, 100, 4))) {
1805 printf("unlock at 100 succeeded! This is a locking bug\n");
1809 status
= cli_unlock(cli
, fnum1
, 0, 4);
1810 if (NT_STATUS_IS_OK(status
)) {
1811 printf("unlock1 succeeded! This is a locking bug\n");
1814 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1815 NT_STATUS_RANGE_NOT_LOCKED
)) {
1820 status
= cli_unlock(cli
, fnum1
, 0, 8);
1821 if (NT_STATUS_IS_OK(status
)) {
1822 printf("unlock2 succeeded! This is a locking bug\n");
1825 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1826 NT_STATUS_RANGE_NOT_LOCKED
)) {
1831 status
= cli_lock32(cli
, fnum3
, 0, 4, 0, WRITE_LOCK
);
1832 if (NT_STATUS_IS_OK(status
)) {
1833 printf("lock3 succeeded! This is a locking bug\n");
1836 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1837 NT_STATUS_LOCK_NOT_GRANTED
)) {
1844 status
= cli_close(cli
, fnum1
);
1845 if (!NT_STATUS_IS_OK(status
)) {
1846 printf("close1 failed (%s)\n", nt_errstr(status
));
1850 status
= cli_close(cli
, fnum2
);
1851 if (!NT_STATUS_IS_OK(status
)) {
1852 printf("close2 failed (%s)\n", nt_errstr(status
));
1856 status
= cli_close(cli
, fnum3
);
1857 if (!NT_STATUS_IS_OK(status
)) {
1858 printf("close3 failed (%s)\n", nt_errstr(status
));
1862 if (!torture_close_connection(cli
)) {
1866 printf("locktest2 finished\n");
1873 This test checks that
1875 1) the server supports the full offset range in lock requests
1877 static bool run_locktest3(int dummy
)
1879 static struct cli_state
*cli1
, *cli2
;
1880 const char *fname
= "\\lockt3.lck";
1881 uint16_t fnum1
, fnum2
;
1884 bool correct
= True
;
1887 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1889 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
1892 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
1893 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
1895 printf("starting locktest3\n");
1897 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1899 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
1901 if (!NT_STATUS_IS_OK(status
)) {
1902 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
1906 status
= cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
1907 if (!NT_STATUS_IS_OK(status
)) {
1908 printf("open2 of %s failed (%s)\n", fname
, nt_errstr(status
));
1912 for (offset
=i
=0;i
<torture_numops
;i
++) {
1915 status
= cli_lock32(cli1
, fnum1
, offset
-1, 1, 0, WRITE_LOCK
);
1916 if (!NT_STATUS_IS_OK(status
)) {
1917 printf("lock1 %d failed (%s)\n",
1923 status
= cli_lock32(cli2
, fnum2
, offset
-2, 1, 0, WRITE_LOCK
);
1924 if (!NT_STATUS_IS_OK(status
)) {
1925 printf("lock2 %d failed (%s)\n",
1932 for (offset
=i
=0;i
<torture_numops
;i
++) {
1935 status
= cli_lock32(cli1
, fnum1
, offset
-2, 1, 0, WRITE_LOCK
);
1936 if (NT_STATUS_IS_OK(status
)) {
1937 printf("error: lock1 %d succeeded!\n", i
);
1941 status
= cli_lock32(cli2
, fnum2
, offset
-1, 1, 0, WRITE_LOCK
);
1942 if (NT_STATUS_IS_OK(status
)) {
1943 printf("error: lock2 %d succeeded!\n", i
);
1947 status
= cli_lock32(cli1
, fnum1
, offset
-1, 1, 0, WRITE_LOCK
);
1948 if (NT_STATUS_IS_OK(status
)) {
1949 printf("error: lock3 %d succeeded!\n", i
);
1953 status
= cli_lock32(cli2
, fnum2
, offset
-2, 1, 0, WRITE_LOCK
);
1954 if (NT_STATUS_IS_OK(status
)) {
1955 printf("error: lock4 %d succeeded!\n", i
);
1960 for (offset
=i
=0;i
<torture_numops
;i
++) {
1963 status
= cli_unlock(cli1
, fnum1
, offset
-1, 1);
1964 if (!NT_STATUS_IS_OK(status
)) {
1965 printf("unlock1 %d failed (%s)\n",
1971 status
= cli_unlock(cli2
, fnum2
, offset
-2, 1);
1972 if (!NT_STATUS_IS_OK(status
)) {
1973 printf("unlock2 %d failed (%s)\n",
1980 status
= cli_close(cli1
, fnum1
);
1981 if (!NT_STATUS_IS_OK(status
)) {
1982 printf("close1 failed (%s)\n", nt_errstr(status
));
1986 status
= cli_close(cli2
, fnum2
);
1987 if (!NT_STATUS_IS_OK(status
)) {
1988 printf("close2 failed (%s)\n", nt_errstr(status
));
1992 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1993 if (!NT_STATUS_IS_OK(status
)) {
1994 printf("unlink failed (%s)\n", nt_errstr(status
));
1998 if (!torture_close_connection(cli1
)) {
2002 if (!torture_close_connection(cli2
)) {
2006 printf("finished locktest3\n");
2011 static bool test_cli_read(struct cli_state
*cli
, uint16_t fnum
,
2012 char *buf
, off_t offset
, size_t size
,
2013 size_t *nread
, size_t expect
)
2018 status
= cli_read(cli
, fnum
, buf
, offset
, size
, &l_nread
);
2020 if(!NT_STATUS_IS_OK(status
)) {
2022 } else if (l_nread
!= expect
) {
2033 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2034 printf("** "); correct = False; \
2038 looks at overlapping locks
2040 static bool run_locktest4(int dummy
)
2042 static struct cli_state
*cli1
, *cli2
;
2043 const char *fname
= "\\lockt4.lck";
2044 uint16_t fnum1
, fnum2
, f
;
2047 bool correct
= True
;
2050 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
2054 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2055 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
2057 printf("starting locktest4\n");
2059 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2061 cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
2062 cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
2064 memset(buf
, 0, sizeof(buf
));
2066 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, sizeof(buf
),
2068 if (!NT_STATUS_IS_OK(status
)) {
2069 printf("Failed to create file: %s\n", nt_errstr(status
));
2074 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 4, 0, WRITE_LOCK
)) &&
2075 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 2, 4, 0, WRITE_LOCK
));
2076 EXPECTED(ret
, False
);
2077 printf("the same process %s set overlapping write locks\n", ret
?"can":"cannot");
2079 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 10, 4, 0, READ_LOCK
)) &&
2080 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 12, 4, 0, READ_LOCK
));
2081 EXPECTED(ret
, True
);
2082 printf("the same process %s set overlapping read locks\n", ret
?"can":"cannot");
2084 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 20, 4, 0, WRITE_LOCK
)) &&
2085 NT_STATUS_IS_OK(cli_lock32(cli2
, fnum2
, 22, 4, 0, WRITE_LOCK
));
2086 EXPECTED(ret
, False
);
2087 printf("a different connection %s set overlapping write locks\n", ret
?"can":"cannot");
2089 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 30, 4, 0, READ_LOCK
)) &&
2090 NT_STATUS_IS_OK(cli_lock32(cli2
, fnum2
, 32, 4, 0, READ_LOCK
));
2091 EXPECTED(ret
, True
);
2092 printf("a different connection %s set overlapping read locks\n", ret
?"can":"cannot");
2094 ret
= (cli_setpid(cli1
, 1),
2095 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 40, 4, 0, WRITE_LOCK
))) &&
2096 (cli_setpid(cli1
, 2),
2097 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 42, 4, 0, WRITE_LOCK
)));
2098 EXPECTED(ret
, False
);
2099 printf("a different pid %s set overlapping write locks\n", ret
?"can":"cannot");
2101 ret
= (cli_setpid(cli1
, 1),
2102 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 50, 4, 0, READ_LOCK
))) &&
2103 (cli_setpid(cli1
, 2),
2104 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 52, 4, 0, READ_LOCK
)));
2105 EXPECTED(ret
, True
);
2106 printf("a different pid %s set overlapping read locks\n", ret
?"can":"cannot");
2108 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 60, 4, 0, READ_LOCK
)) &&
2109 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 60, 4, 0, READ_LOCK
));
2110 EXPECTED(ret
, True
);
2111 printf("the same process %s set the same read lock twice\n", ret
?"can":"cannot");
2113 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 70, 4, 0, WRITE_LOCK
)) &&
2114 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 70, 4, 0, WRITE_LOCK
));
2115 EXPECTED(ret
, False
);
2116 printf("the same process %s set the same write lock twice\n", ret
?"can":"cannot");
2118 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 80, 4, 0, READ_LOCK
)) &&
2119 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 80, 4, 0, WRITE_LOCK
));
2120 EXPECTED(ret
, False
);
2121 printf("the same process %s overlay a read lock with a write lock\n", ret
?"can":"cannot");
2123 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 90, 4, 0, WRITE_LOCK
)) &&
2124 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 90, 4, 0, READ_LOCK
));
2125 EXPECTED(ret
, True
);
2126 printf("the same process %s overlay a write lock with a read lock\n", ret
?"can":"cannot");
2128 ret
= (cli_setpid(cli1
, 1),
2129 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 100, 4, 0, WRITE_LOCK
))) &&
2130 (cli_setpid(cli1
, 2),
2131 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 100, 4, 0, READ_LOCK
)));
2132 EXPECTED(ret
, False
);
2133 printf("a different pid %s overlay a write lock with a read lock\n", ret
?"can":"cannot");
2135 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 110, 4, 0, READ_LOCK
)) &&
2136 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 112, 4, 0, READ_LOCK
)) &&
2137 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 110, 6));
2138 EXPECTED(ret
, False
);
2139 printf("the same process %s coalesce read locks\n", ret
?"can":"cannot");
2142 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 120, 4, 0, WRITE_LOCK
)) &&
2143 test_cli_read(cli2
, fnum2
, buf
, 120, 4, NULL
, 4);
2144 EXPECTED(ret
, False
);
2145 printf("this server %s strict write locking\n", ret
?"doesn't do":"does");
2147 status
= cli_lock32(cli1
, fnum1
, 130, 4, 0, READ_LOCK
);
2148 ret
= NT_STATUS_IS_OK(status
);
2150 status
= cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
, 130, 4,
2152 ret
= NT_STATUS_IS_OK(status
);
2154 EXPECTED(ret
, False
);
2155 printf("this server %s strict read locking\n", ret
?"doesn't do":"does");
2158 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 140, 4, 0, READ_LOCK
)) &&
2159 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 140, 4, 0, READ_LOCK
)) &&
2160 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 140, 4)) &&
2161 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 140, 4));
2162 EXPECTED(ret
, True
);
2163 printf("this server %s do recursive read locking\n", ret
?"does":"doesn't");
2166 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 150, 4, 0, WRITE_LOCK
)) &&
2167 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 150, 4, 0, READ_LOCK
)) &&
2168 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 150, 4)) &&
2169 test_cli_read(cli2
, fnum2
, buf
, 150, 4, NULL
, 4) &&
2170 !(NT_STATUS_IS_OK(cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
,
2172 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 150, 4));
2173 EXPECTED(ret
, True
);
2174 printf("this server %s do recursive lock overlays\n", ret
?"does":"doesn't");
2176 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 160, 4, 0, READ_LOCK
)) &&
2177 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 160, 4)) &&
2178 NT_STATUS_IS_OK(cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
,
2180 test_cli_read(cli2
, fnum2
, buf
, 160, 4, NULL
, 4);
2181 EXPECTED(ret
, True
);
2182 printf("the same process %s remove a read lock using write locking\n", ret
?"can":"cannot");
2184 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 170, 4, 0, WRITE_LOCK
)) &&
2185 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 170, 4)) &&
2186 NT_STATUS_IS_OK(cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
,
2188 test_cli_read(cli2
, fnum2
, buf
, 170, 4, NULL
, 4);
2189 EXPECTED(ret
, True
);
2190 printf("the same process %s remove a write lock using read locking\n", ret
?"can":"cannot");
2192 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 190, 4, 0, WRITE_LOCK
)) &&
2193 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 190, 4, 0, READ_LOCK
)) &&
2194 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 190, 4)) &&
2195 !NT_STATUS_IS_OK(cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
,
2197 test_cli_read(cli2
, fnum2
, buf
, 190, 4, NULL
, 4);
2198 EXPECTED(ret
, True
);
2199 printf("the same process %s remove the first lock first\n", ret
?"does":"doesn't");
2201 cli_close(cli1
, fnum1
);
2202 cli_close(cli2
, fnum2
);
2203 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
2204 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &f
);
2205 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 8, 0, READ_LOCK
)) &&
2206 NT_STATUS_IS_OK(cli_lock32(cli1
, f
, 0, 1, 0, READ_LOCK
)) &&
2207 NT_STATUS_IS_OK(cli_close(cli1
, fnum1
)) &&
2208 NT_STATUS_IS_OK(cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
)) &&
2209 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 7, 1, 0, WRITE_LOCK
));
2211 cli_close(cli1
, fnum1
);
2212 EXPECTED(ret
, True
);
2213 printf("the server %s have the NT byte range lock bug\n", !ret
?"does":"doesn't");
2216 cli_close(cli1
, fnum1
);
2217 cli_close(cli2
, fnum2
);
2218 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2219 torture_close_connection(cli1
);
2220 torture_close_connection(cli2
);
2222 printf("finished locktest4\n");
2227 looks at lock upgrade/downgrade.
2229 static bool run_locktest5(int dummy
)
2231 static struct cli_state
*cli1
, *cli2
;
2232 const char *fname
= "\\lockt5.lck";
2233 uint16_t fnum1
, fnum2
, fnum3
;
2236 bool correct
= True
;
2239 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
2243 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2244 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
2246 printf("starting locktest5\n");
2248 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2250 cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
2251 cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
2252 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum3
);
2254 memset(buf
, 0, sizeof(buf
));
2256 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, sizeof(buf
),
2258 if (!NT_STATUS_IS_OK(status
)) {
2259 printf("Failed to create file: %s\n", nt_errstr(status
));
2264 /* Check for NT bug... */
2265 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 8, 0, READ_LOCK
)) &&
2266 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum3
, 0, 1, 0, READ_LOCK
));
2267 cli_close(cli1
, fnum1
);
2268 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
2269 status
= cli_lock32(cli1
, fnum1
, 7, 1, 0, WRITE_LOCK
);
2270 ret
= NT_STATUS_IS_OK(status
);
2271 EXPECTED(ret
, True
);
2272 printf("this server %s the NT locking bug\n", ret
? "doesn't have" : "has");
2273 cli_close(cli1
, fnum1
);
2274 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
2275 cli_unlock(cli1
, fnum3
, 0, 1);
2277 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 4, 0, WRITE_LOCK
)) &&
2278 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 1, 1, 0, READ_LOCK
));
2279 EXPECTED(ret
, True
);
2280 printf("the same process %s overlay a write with a read lock\n", ret
?"can":"cannot");
2282 status
= cli_lock32(cli2
, fnum2
, 0, 4, 0, READ_LOCK
);
2283 ret
= NT_STATUS_IS_OK(status
);
2284 EXPECTED(ret
, False
);
2286 printf("a different process %s get a read lock on the first process lock stack\n", ret
?"can":"cannot");
2288 /* Unlock the process 2 lock. */
2289 cli_unlock(cli2
, fnum2
, 0, 4);
2291 status
= cli_lock32(cli1
, fnum3
, 0, 4, 0, READ_LOCK
);
2292 ret
= NT_STATUS_IS_OK(status
);
2293 EXPECTED(ret
, False
);
2295 printf("the same process on a different fnum %s get a read lock\n", ret
?"can":"cannot");
2297 /* Unlock the process 1 fnum3 lock. */
2298 cli_unlock(cli1
, fnum3
, 0, 4);
2300 /* Stack 2 more locks here. */
2301 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 4, 0, READ_LOCK
)) &&
2302 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 4, 0, READ_LOCK
));
2304 EXPECTED(ret
, True
);
2305 printf("the same process %s stack read locks\n", ret
?"can":"cannot");
2307 /* Unlock the first process lock, then check this was the WRITE lock that was
2310 ret
= NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 0, 4)) &&
2311 NT_STATUS_IS_OK(cli_lock32(cli2
, fnum2
, 0, 4, 0, READ_LOCK
));
2313 EXPECTED(ret
, True
);
2314 printf("the first unlock removes the %s lock\n", ret
?"WRITE":"READ");
2316 /* Unlock the process 2 lock. */
2317 cli_unlock(cli2
, fnum2
, 0, 4);
2319 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2321 ret
= NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 1, 1)) &&
2322 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 0, 4)) &&
2323 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 0, 4));
2325 EXPECTED(ret
, True
);
2326 printf("the same process %s unlock the stack of 4 locks\n", ret
?"can":"cannot");
2328 /* Ensure the next unlock fails. */
2329 ret
= NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 0, 4));
2330 EXPECTED(ret
, False
);
2331 printf("the same process %s count the lock stack\n", !ret
?"can":"cannot");
2333 /* Ensure connection 2 can get a write lock. */
2334 status
= cli_lock32(cli2
, fnum2
, 0, 4, 0, WRITE_LOCK
);
2335 ret
= NT_STATUS_IS_OK(status
);
2336 EXPECTED(ret
, True
);
2338 printf("a different process %s get a write lock on the unlocked stack\n", ret
?"can":"cannot");
2342 cli_close(cli1
, fnum1
);
2343 cli_close(cli2
, fnum2
);
2344 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2345 if (!torture_close_connection(cli1
)) {
2348 if (!torture_close_connection(cli2
)) {
2352 printf("finished locktest5\n");
2358 tries the unusual lockingX locktype bits
2360 static bool run_locktest6(int dummy
)
2362 static struct cli_state
*cli
;
2363 const char *fname
[1] = { "\\lock6.txt" };
2368 if (!torture_open_connection(&cli
, 0)) {
2372 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
2374 printf("starting locktest6\n");
2377 printf("Testing %s\n", fname
[i
]);
2379 cli_unlink(cli
, fname
[i
], FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2381 cli_openx(cli
, fname
[i
], O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
2382 status
= cli_locktype(cli
, fnum
, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE
);
2383 cli_close(cli
, fnum
);
2384 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status
));
2386 cli_openx(cli
, fname
[i
], O_RDWR
, DENY_NONE
, &fnum
);
2387 status
= cli_locktype(cli
, fnum
, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK
);
2388 cli_close(cli
, fnum
);
2389 printf("CANCEL_LOCK gave %s\n", nt_errstr(status
));
2391 cli_unlink(cli
, fname
[i
], FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2394 torture_close_connection(cli
);
2396 printf("finished locktest6\n");
2400 static bool run_locktest7(int dummy
)
2402 struct cli_state
*cli1
;
2403 const char *fname
= "\\lockt7.lck";
2406 bool correct
= False
;
2410 if (!torture_open_connection(&cli1
, 0)) {
2414 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2416 printf("starting locktest7\n");
2418 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2420 cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
2422 memset(buf
, 0, sizeof(buf
));
2424 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, sizeof(buf
),
2426 if (!NT_STATUS_IS_OK(status
)) {
2427 printf("Failed to create file: %s\n", nt_errstr(status
));
2431 cli_setpid(cli1
, 1);
2433 status
= cli_lock32(cli1
, fnum1
, 130, 4, 0, READ_LOCK
);
2434 if (!NT_STATUS_IS_OK(status
)) {
2435 printf("Unable to apply read lock on range 130:4, "
2436 "error was %s\n", nt_errstr(status
));
2439 printf("pid1 successfully locked range 130:4 for READ\n");
2442 status
= cli_read(cli1
, fnum1
, buf
, 130, 4, &nread
);
2443 if (!NT_STATUS_IS_OK(status
)) {
2444 printf("pid1 unable to read the range 130:4, error was %s\n",
2447 } else if (nread
!= 4) {
2448 printf("pid1 unable to read the range 130:4, "
2449 "recv %ld req %d\n", (unsigned long)nread
, 4);
2452 printf("pid1 successfully read the range 130:4\n");
2455 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
2456 if (!NT_STATUS_IS_OK(status
)) {
2457 printf("pid1 unable to write to the range 130:4, error was "
2458 "%s\n", nt_errstr(status
));
2459 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
2460 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2464 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2468 cli_setpid(cli1
, 2);
2470 status
= cli_read(cli1
, fnum1
, buf
, 130, 4, &nread
);
2471 if (!NT_STATUS_IS_OK(status
)) {
2472 printf("pid2 unable to read the range 130:4, error was %s\n",
2475 } else if (nread
!= 4) {
2476 printf("pid2 unable to read the range 130:4, "
2477 "recv %ld req %d\n", (unsigned long)nread
, 4);
2480 printf("pid2 successfully read the range 130:4\n");
2483 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
2484 if (!NT_STATUS_IS_OK(status
)) {
2485 printf("pid2 unable to write to the range 130:4, error was "
2486 "%s\n", nt_errstr(status
));
2487 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
2488 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2492 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2496 cli_setpid(cli1
, 1);
2497 cli_unlock(cli1
, fnum1
, 130, 4);
2499 status
= cli_lock32(cli1
, fnum1
, 130, 4, 0, WRITE_LOCK
);
2500 if (!NT_STATUS_IS_OK(status
)) {
2501 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status
));
2504 printf("pid1 successfully locked range 130:4 for WRITE\n");
2507 status
= cli_read(cli1
, fnum1
, buf
, 130, 4, &nread
);
2508 if (!NT_STATUS_IS_OK(status
)) {
2509 printf("pid1 unable to read the range 130:4, error was %s\n",
2512 } else if (nread
!= 4) {
2513 printf("pid1 unable to read the range 130:4, "
2514 "recv %ld req %d\n", (unsigned long)nread
, 4);
2517 printf("pid1 successfully read the range 130:4\n");
2520 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
2521 if (!NT_STATUS_IS_OK(status
)) {
2522 printf("pid1 unable to write to the range 130:4, error was "
2523 "%s\n", nt_errstr(status
));
2526 printf("pid1 successfully wrote to the range 130:4\n");
2529 cli_setpid(cli1
, 2);
2531 status
= cli_read(cli1
, fnum1
, buf
, 130, 4, &nread
);
2532 if (!NT_STATUS_IS_OK(status
)) {
2533 printf("pid2 unable to read the range 130:4, error was "
2534 "%s\n", nt_errstr(status
));
2535 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
2536 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2540 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2541 (unsigned long)nread
);
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_unlock(cli1
, fnum1
, 130, 0);
2562 cli_close(cli1
, fnum1
);
2563 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2564 torture_close_connection(cli1
);
2566 printf("finished locktest7\n");
2571 * This demonstrates a problem with our use of GPFS share modes: A file
2572 * descriptor sitting in the pending close queue holding a GPFS share mode
2573 * blocks opening a file another time. Happens with Word 2007 temp files.
2574 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2575 * open is denied with NT_STATUS_SHARING_VIOLATION.
2578 static bool run_locktest8(int dummy
)
2580 struct cli_state
*cli1
;
2581 const char *fname
= "\\lockt8.lck";
2582 uint16_t fnum1
, fnum2
;
2584 bool correct
= False
;
2587 if (!torture_open_connection(&cli1
, 0)) {
2591 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2593 printf("starting locktest8\n");
2595 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2597 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_WRITE
,
2599 if (!NT_STATUS_IS_OK(status
)) {
2600 d_fprintf(stderr
, "cli_openx returned %s\n", nt_errstr(status
));
2604 memset(buf
, 0, sizeof(buf
));
2606 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum2
);
2607 if (!NT_STATUS_IS_OK(status
)) {
2608 d_fprintf(stderr
, "cli_openx second time returned %s\n",
2613 status
= cli_lock32(cli1
, fnum2
, 1, 1, 0, READ_LOCK
);
2614 if (!NT_STATUS_IS_OK(status
)) {
2615 printf("Unable to apply read lock on range 1:1, error was "
2616 "%s\n", nt_errstr(status
));
2620 status
= cli_close(cli1
, fnum1
);
2621 if (!NT_STATUS_IS_OK(status
)) {
2622 d_fprintf(stderr
, "cli_close(fnum1) %s\n", nt_errstr(status
));
2626 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
2627 if (!NT_STATUS_IS_OK(status
)) {
2628 d_fprintf(stderr
, "cli_openx third time returned %s\n",
2636 cli_close(cli1
, fnum1
);
2637 cli_close(cli1
, fnum2
);
2638 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2639 torture_close_connection(cli1
);
2641 printf("finished locktest8\n");
2646 * This test is designed to be run in conjunction with
2647 * external NFS or POSIX locks taken in the filesystem.
2648 * It checks that the smbd server will block until the
2649 * lock is released and then acquire it. JRA.
2652 static bool got_alarm
;
2653 static struct cli_state
*alarm_cli
;
2655 static void alarm_handler(int dummy
)
2660 static void alarm_handler_parent(int dummy
)
2662 smbXcli_conn_disconnect(alarm_cli
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
2665 static void do_local_lock(const char *fname
, int read_fd
, int write_fd
)
2670 const char *local_pathname
= NULL
;
2673 local_pathname
= talloc_asprintf(talloc_tos(),
2674 "%s/%s", local_path
, fname
);
2675 if (!local_pathname
) {
2676 printf("child: alloc fail\n");
2680 unlink(local_pathname
);
2681 fd
= open(local_pathname
, O_RDWR
|O_CREAT
, 0666);
2683 printf("child: open of %s failed %s.\n",
2684 local_pathname
, strerror(errno
));
2688 /* Now take a fcntl lock. */
2689 lock
.l_type
= F_WRLCK
;
2690 lock
.l_whence
= SEEK_SET
;
2693 lock
.l_pid
= getpid();
2695 ret
= fcntl(fd
,F_SETLK
,&lock
);
2697 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2698 local_pathname
, strerror(errno
));
2701 printf("child: got lock 0:4 on file %s.\n",
2706 CatchSignal(SIGALRM
, alarm_handler
);
2708 /* Signal the parent. */
2709 if (write(write_fd
, &c
, 1) != 1) {
2710 printf("child: start signal fail %s.\n",
2717 /* Wait for the parent to be ready. */
2718 if (read(read_fd
, &c
, 1) != 1) {
2719 printf("child: reply signal fail %s.\n",
2727 printf("child: released lock 0:4 on file %s.\n",
2733 static bool _run_locktest9X(const char *fname
, int timeout
)
2735 struct cli_state
*cli1
;
2736 char *fpath
= talloc_asprintf(talloc_tos(), "\\%s", fname
);
2738 bool correct
= False
;
2739 int pipe_in
[2], pipe_out
[2];
2743 struct timeval start
;
2747 printf("starting locktest9X: %s\n", fname
);
2749 if (local_path
== NULL
) {
2750 d_fprintf(stderr
, "locktest9X must be given a local path via -l <localpath>\n");
2754 if (pipe(pipe_in
) == -1 || pipe(pipe_out
) == -1) {
2759 if (child_pid
== -1) {
2763 if (child_pid
== 0) {
2765 do_local_lock(fname
, pipe_out
[0], pipe_in
[1]);
2775 ret
= read(pipe_in
[0], &c
, 1);
2777 d_fprintf(stderr
, "failed to read start signal from child. %s\n",
2782 if (!torture_open_connection(&cli1
, 0)) {
2786 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2788 status
= cli_openx(cli1
, fpath
, O_RDWR
, DENY_NONE
,
2790 if (!NT_STATUS_IS_OK(status
)) {
2791 d_fprintf(stderr
, "cli_openx returned %s\n", nt_errstr(status
));
2795 /* Ensure the child has the lock. */
2796 status
= cli_lock32(cli1
, fnum
, 0, 4, 0, WRITE_LOCK
);
2797 if (NT_STATUS_IS_OK(status
)) {
2798 d_fprintf(stderr
, "Got the lock on range 0:4 - this should not happen !\n");
2801 d_printf("Child has the lock.\n");
2804 /* Tell the child to wait 5 seconds then exit. */
2805 ret
= write(pipe_out
[1], &c
, 1);
2807 d_fprintf(stderr
, "failed to send exit signal to child. %s\n",
2812 /* Wait 20 seconds for the lock. */
2814 CatchSignal(SIGALRM
, alarm_handler_parent
);
2817 start
= timeval_current();
2819 status
= cli_lock32(cli1
, fnum
, 0, 4, timeout
, WRITE_LOCK
);
2820 if (!NT_STATUS_IS_OK(status
)) {
2821 d_fprintf(stderr
, "Unable to apply write lock on range 0:4, error was "
2822 "%s\n", nt_errstr(status
));
2827 seconds
= timeval_elapsed(&start
);
2829 printf("Parent got the lock after %.2f seconds.\n",
2832 status
= cli_close(cli1
, fnum
);
2833 if (!NT_STATUS_IS_OK(status
)) {
2834 d_fprintf(stderr
, "cli_close(fnum1) %s\n", nt_errstr(status
));
2841 cli_close(cli1
, fnum
);
2842 torture_close_connection(cli1
);
2846 printf("finished locktest9X: %s\n", fname
);
2850 static bool run_locktest9a(int dummy
)
2852 return _run_locktest9X("lock9a.dat", -1);
2855 static bool run_locktest9b(int dummy
)
2857 return _run_locktest9X("lock9b.dat", 10000);
2860 struct locktest10_state
{
2865 static void locktest10_lockingx_done(struct tevent_req
*subreq
);
2866 static void locktest10_read_andx_done(struct tevent_req
*subreq
);
2868 static bool run_locktest10(int dummy
)
2870 struct tevent_context
*ev
= NULL
;
2871 struct cli_state
*cli1
= NULL
;
2872 struct cli_state
*cli2
= NULL
;
2873 struct smb1_lock_element lck
= { 0 };
2874 struct tevent_req
*reqs
[2] = { NULL
};
2875 struct tevent_req
*smbreqs
[2] = { NULL
};
2876 const char fname
[] = "\\lockt10.lck";
2877 uint16_t fnum1
, fnum2
;
2881 struct locktest10_state state
= { .ok
= true };
2884 printf("starting locktest10\n");
2886 ev
= samba_tevent_context_init(NULL
);
2888 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
2892 ok
= torture_open_connection(&cli1
, 0);
2896 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2898 ok
= torture_open_connection(&cli2
, 1);
2902 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
2904 status
= cli_openx(cli1
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum1
);
2905 if (!NT_STATUS_IS_OK(status
)) {
2907 "cli_openx failed: %s\n",
2912 status
= cli_writeall(cli1
, fnum1
, 0, &data
, 0, sizeof(data
), NULL
);
2913 if (!NT_STATUS_IS_OK(status
)) {
2915 "cli_writeall failed: %s\n",
2920 status
= cli_openx(cli2
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum2
);
2921 if (!NT_STATUS_IS_OK(status
)) {
2923 "cli_openx failed: %s\n",
2928 status
= cli_locktype(
2929 cli2
, fnum2
, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK
);
2930 if (!NT_STATUS_IS_OK(status
)) {
2932 "cli_locktype failed: %s\n",
2937 lck
= (struct smb1_lock_element
) {
2938 .pid
= cli_getpid(cli1
), .offset
= 0, .length
= 1,
2941 reqs
[0] = cli_lockingx_create(
2943 ev
, /* tevent_context */
2946 LOCKING_ANDX_EXCLUSIVE_LOCK
, /* typeoflock */
2947 0, /* newoplocklevel */
2949 0, /* num_unlocks */
2953 &smbreqs
[0]); /* psmbreq */
2954 if (reqs
[0] == NULL
) {
2955 d_fprintf(stderr
, "cli_lockingx_create failed\n");
2958 tevent_req_set_callback(reqs
[0], locktest10_lockingx_done
, &state
);
2960 reqs
[1] = cli_read_andx_create(
2967 &smbreqs
[1]); /* psmbreq */
2968 if (reqs
[1] == NULL
) {
2969 d_fprintf(stderr
, "cli_read_andx_create failed\n");
2972 tevent_req_set_callback(reqs
[1], locktest10_read_andx_done
, &state
);
2974 status
= smb1cli_req_chain_submit(smbreqs
, ARRAY_SIZE(smbreqs
));
2975 if (!NT_STATUS_IS_OK(status
)) {
2977 "smb1cli_req_chain_submit failed: %s\n",
2982 while (!state
.done
) {
2983 tevent_loop_once(ev
);
2986 torture_close_connection(cli1
);
2995 static void locktest10_lockingx_done(struct tevent_req
*subreq
)
2997 struct locktest10_state
*state
= tevent_req_callback_data_void(subreq
);
3000 status
= cli_lockingx_recv(subreq
);
3001 TALLOC_FREE(subreq
);
3003 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
3004 d_printf("cli_lockingx returned %s\n", nt_errstr(status
));
3009 static void locktest10_read_andx_done(struct tevent_req
*subreq
)
3011 struct locktest10_state
*state
= tevent_req_callback_data_void(subreq
);
3012 ssize_t received
= -1;
3013 uint8_t *rcvbuf
= NULL
;
3016 status
= cli_read_andx_recv(subreq
, &received
, &rcvbuf
);
3018 if (!NT_STATUS_EQUAL(status
, NT_STATUS_REQUEST_ABORTED
)) {
3019 d_printf("cli_read_andx returned %s\n", nt_errstr(status
));
3024 TALLOC_FREE(subreq
);
3027 static bool run_locktest11(int dummy
)
3029 struct cli_state
*cli1
;
3030 const char *fname
= "\\lockt11.lck";
3035 if (!torture_open_connection(&cli1
, 0)) {
3039 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
3041 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3043 status
= cli_openx(cli1
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum
);
3044 if (!NT_STATUS_IS_OK(status
)) {
3046 "cli_openx returned %s\n",
3052 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3053 * returns NT_STATUS_OK
3056 status
= cli_lockingx(
3059 LOCKING_ANDX_CANCEL_LOCK
, /* typeoflock */
3060 0, /* newoplocklevel */
3062 0, /* num_unlocks */
3067 if (!NT_STATUS_IS_OK(status
)) {
3068 d_printf("cli_lockingX returned %s\n", nt_errstr(status
));
3074 cli_close(cli1
, fnum
);
3075 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3080 struct deferred_close_state
{
3081 struct tevent_context
*ev
;
3082 struct cli_state
*cli
;
3086 static void deferred_close_waited(struct tevent_req
*subreq
);
3087 static void deferred_close_done(struct tevent_req
*subreq
);
3089 static struct tevent_req
*deferred_close_send(
3090 TALLOC_CTX
*mem_ctx
,
3091 struct tevent_context
*ev
,
3093 struct cli_state
*cli
,
3096 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3097 struct deferred_close_state
*state
= NULL
;
3098 struct timeval wakeup_time
= timeval_current_ofs(wait_secs
, 0);
3100 req
= tevent_req_create(
3101 mem_ctx
, &state
, struct deferred_close_state
);
3109 subreq
= tevent_wakeup_send(state
, state
->ev
, wakeup_time
);
3110 if (tevent_req_nomem(subreq
, req
)) {
3111 return tevent_req_post(req
, ev
);
3113 tevent_req_set_callback(subreq
, deferred_close_waited
, req
);
3117 static void deferred_close_waited(struct tevent_req
*subreq
)
3119 struct tevent_req
*req
= tevent_req_callback_data(
3120 subreq
, struct tevent_req
);
3121 struct deferred_close_state
*state
= tevent_req_data(
3122 req
, struct deferred_close_state
);
3125 ok
= tevent_wakeup_recv(subreq
);
3126 TALLOC_FREE(subreq
);
3128 tevent_req_oom(req
);
3132 subreq
= cli_close_send(state
, state
->ev
, state
->cli
, state
->fnum
);
3133 if (tevent_req_nomem(subreq
, req
)) {
3136 tevent_req_set_callback(subreq
, deferred_close_done
, req
);
3139 static void deferred_close_done(struct tevent_req
*subreq
)
3141 NTSTATUS status
= cli_close_recv(subreq
);
3142 tevent_req_simple_finish_ntstatus(subreq
, status
);
3145 static NTSTATUS
deferred_close_recv(struct tevent_req
*req
)
3147 return tevent_req_simple_recv_ntstatus(req
);
3150 struct lockread_state
{
3151 struct smb1_lock_element lck
;
3152 struct tevent_req
*reqs
[2];
3153 struct tevent_req
*smbreqs
[2];
3154 NTSTATUS lock_status
;
3155 NTSTATUS read_status
;
3159 static void lockread_lockingx_done(struct tevent_req
*subreq
);
3160 static void lockread_read_andx_done(struct tevent_req
*subreq
);
3162 static struct tevent_req
*lockread_send(
3163 TALLOC_CTX
*mem_ctx
,
3164 struct tevent_context
*ev
,
3165 struct cli_state
*cli
,
3168 struct tevent_req
*req
= NULL
;
3169 struct lockread_state
*state
= NULL
;
3172 req
= tevent_req_create(mem_ctx
, &state
, struct lockread_state
);
3177 state
->lck
= (struct smb1_lock_element
) {
3178 .pid
= cli_getpid(cli
), .offset
= 0, .length
= 1,
3181 state
->reqs
[0] = cli_lockingx_create(
3183 ev
, /* tevent_context */
3186 LOCKING_ANDX_EXCLUSIVE_LOCK
, /* typeoflock */
3187 0, /* newoplocklevel */
3188 10000, /* timeout */
3189 0, /* num_unlocks */
3192 &state
->lck
, /* locks */
3193 &state
->smbreqs
[0]); /* psmbreq */
3194 if (tevent_req_nomem(state
->reqs
[0], req
)) {
3195 return tevent_req_post(req
, ev
);
3197 tevent_req_set_callback(
3198 state
->reqs
[0], lockread_lockingx_done
, req
);
3200 state
->reqs
[1] = cli_read_andx_create(
3207 &state
->smbreqs
[1]); /* psmbreq */
3208 if (tevent_req_nomem(state
->reqs
[1], req
)) {
3209 return tevent_req_post(req
, ev
);
3211 tevent_req_set_callback(
3212 state
->reqs
[1], lockread_read_andx_done
, req
);
3214 status
= smb1cli_req_chain_submit(state
->smbreqs
, 2);
3215 if (tevent_req_nterror(req
, status
)) {
3216 return tevent_req_post(req
, ev
);
3221 static void lockread_lockingx_done(struct tevent_req
*subreq
)
3223 struct tevent_req
*req
= tevent_req_callback_data(
3224 subreq
, struct tevent_req
);
3225 struct lockread_state
*state
= tevent_req_data(
3226 req
, struct lockread_state
);
3227 state
->lock_status
= cli_lockingx_recv(subreq
);
3228 TALLOC_FREE(subreq
);
3230 "lockingx returned %s\n",
3231 nt_errstr(state
->lock_status
));
3234 static void lockread_read_andx_done(struct tevent_req
*subreq
)
3236 struct tevent_req
*req
= tevent_req_callback_data(
3237 subreq
, struct tevent_req
);
3238 struct lockread_state
*state
= tevent_req_data(
3239 req
, struct lockread_state
);
3240 ssize_t received
= -1;
3241 uint8_t *rcvbuf
= NULL
;
3243 state
->read_status
= cli_read_andx_recv(subreq
, &received
, &rcvbuf
);
3246 "read returned %s\n",
3247 nt_errstr(state
->read_status
));
3249 if (!NT_STATUS_IS_OK(state
->read_status
)) {
3250 TALLOC_FREE(subreq
);
3251 tevent_req_done(req
);
3256 state
->readbuf
= talloc_memdup(state
, rcvbuf
, received
);
3257 TALLOC_FREE(subreq
);
3258 if (tevent_req_nomem(state
->readbuf
, req
)) {
3262 TALLOC_FREE(subreq
);
3263 tevent_req_done(req
);
3266 static NTSTATUS
lockread_recv(
3267 struct tevent_req
*req
,
3268 NTSTATUS
*lock_status
,
3269 NTSTATUS
*read_status
,
3270 TALLOC_CTX
*mem_ctx
,
3273 struct lockread_state
*state
= tevent_req_data(
3274 req
, struct lockread_state
);
3277 if (tevent_req_is_nterror(req
, &status
)) {
3281 *lock_status
= state
->lock_status
;
3282 *read_status
= state
->read_status
;
3283 if (state
->readbuf
!= NULL
) {
3284 *read_buf
= talloc_move(mem_ctx
, &state
->readbuf
);
3289 return NT_STATUS_OK
;
3292 struct lock12_state
{
3296 static void lock12_closed(struct tevent_req
*subreq
);
3297 static void lock12_read(struct tevent_req
*subreq
);
3299 static struct tevent_req
*lock12_send(
3300 TALLOC_CTX
*mem_ctx
,
3301 struct tevent_context
*ev
,
3302 struct cli_state
*cli
,
3306 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3307 struct lock12_state
*state
= NULL
;
3309 req
= tevent_req_create(mem_ctx
, &state
, struct lock12_state
);
3314 subreq
= deferred_close_send(state
, ev
, 1, cli
, fnum1
);
3315 if (tevent_req_nomem(subreq
, req
)) {
3316 return tevent_req_post(req
, ev
);
3318 tevent_req_set_callback(subreq
, lock12_closed
, req
);
3320 subreq
= lockread_send(state
, ev
, cli
, fnum2
);
3321 if (tevent_req_nomem(subreq
, req
)) {
3322 return tevent_req_post(req
, ev
);
3324 tevent_req_set_callback(subreq
, lock12_read
, req
);
3329 static void lock12_closed(struct tevent_req
*subreq
)
3331 struct tevent_req
*req
= tevent_req_callback_data(
3332 subreq
, struct tevent_req
);
3335 status
= deferred_close_recv(subreq
);
3336 TALLOC_FREE(subreq
);
3337 DBG_DEBUG("close returned %s\n", nt_errstr(status
));
3338 if (tevent_req_nterror(req
, status
)) {
3343 static void lock12_read(struct tevent_req
*subreq
)
3345 struct tevent_req
*req
= tevent_req_callback_data(
3346 subreq
, struct tevent_req
);
3347 struct lock12_state
*state
= tevent_req_data(
3348 req
, struct lock12_state
);
3349 NTSTATUS status
, lock_status
, read_status
;
3350 uint8_t *buf
= NULL
;
3352 status
= lockread_recv(
3353 subreq
, &lock_status
, &read_status
, state
, &buf
);
3354 TALLOC_FREE(subreq
);
3355 if (tevent_req_nterror(req
, status
) ||
3356 tevent_req_nterror(req
, lock_status
) ||
3357 tevent_req_nterror(req
, read_status
)) {
3360 tevent_req_done(req
);
3363 static NTSTATUS
lock12_recv(struct tevent_req
*req
)
3368 if (tevent_req_is_nterror(req
, &status
)) {
3371 return NT_STATUS_OK
;
3374 static bool run_locktest12(int dummy
)
3376 struct tevent_context
*ev
= NULL
;
3377 struct tevent_req
*req
= NULL
;
3378 struct cli_state
*cli
= NULL
;
3379 const char fname
[] = "\\lockt12.lck";
3380 uint16_t fnum1
, fnum2
;
3386 printf("starting locktest12\n");
3388 ev
= samba_tevent_context_init(NULL
);
3390 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
3394 ok
= torture_open_connection(&cli
, 0);
3398 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3400 status
= cli_openx(cli
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum1
);
3401 if (!NT_STATUS_IS_OK(status
)) {
3403 "cli_openx failed: %s\n",
3408 status
= cli_openx(cli
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum2
);
3409 if (!NT_STATUS_IS_OK(status
)) {
3411 "cli_openx failed: %s\n",
3416 status
= cli_writeall(cli
, fnum1
, 0, &data
, 0, sizeof(data
), NULL
);
3417 if (!NT_STATUS_IS_OK(status
)) {
3419 "cli_writeall failed: %s\n",
3424 status
= cli_locktype(
3425 cli
, fnum1
, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK
);
3426 if (!NT_STATUS_IS_OK(status
)) {
3428 "cli_locktype failed: %s\n",
3433 req
= lock12_send(ev
, ev
, cli
, fnum1
, fnum2
);
3435 d_fprintf(stderr
, "lock12_send failed\n");
3439 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
3441 d_fprintf(stderr
, "tevent_req_poll_ntstatus failed\n");
3445 if (!NT_STATUS_IS_OK(status
)) {
3447 "tevent_req_poll_ntstatus returned %s\n",
3452 status
= lock12_recv(req
);
3453 if (!NT_STATUS_IS_OK(status
)) {
3454 d_fprintf(stderr
, "lock12 returned %s\n", nt_errstr(status
));
3461 torture_close_connection(cli
);
3466 struct lock_ntcancel_state
{
3467 struct timeval start
;
3468 struct smb1_lock_element lck
;
3469 struct tevent_req
*subreq
;
3472 static void lock_ntcancel_waited(struct tevent_req
*subreq
);
3473 static void lock_ntcancel_done(struct tevent_req
*subreq
);
3475 static struct tevent_req
*lock_ntcancel_send(
3476 TALLOC_CTX
*mem_ctx
,
3477 struct tevent_context
*ev
,
3478 struct cli_state
*cli
,
3481 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3482 struct lock_ntcancel_state
*state
= NULL
;
3484 req
= tevent_req_create(mem_ctx
, &state
, struct lock_ntcancel_state
);
3488 state
->lck
= (struct smb1_lock_element
) {
3489 .pid
= cli_getpid(cli
), .offset
= 0, .length
= 1,
3491 state
->start
= timeval_current();
3493 state
->subreq
= cli_lockingx_send(
3494 state
, /* mem_ctx */
3495 ev
, /* tevent_context */
3498 LOCKING_ANDX_EXCLUSIVE_LOCK
, /* typeoflock */
3499 0, /* newoplocklevel */
3500 10000, /* timeout */
3501 0, /* num_unlocks */
3504 &state
->lck
); /* locks */
3505 if (tevent_req_nomem(state
->subreq
, req
)) {
3506 return tevent_req_post(req
, ev
);
3508 tevent_req_set_callback(state
->subreq
, lock_ntcancel_done
, req
);
3510 subreq
= tevent_wakeup_send(state
, ev
, timeval_current_ofs(1, 0));
3511 if (tevent_req_nomem(subreq
, req
)) {
3512 return tevent_req_post(req
, ev
);
3514 tevent_req_set_callback(subreq
, lock_ntcancel_waited
, req
);
3518 static void lock_ntcancel_waited(struct tevent_req
*subreq
)
3520 struct tevent_req
*req
= tevent_req_callback_data(
3521 subreq
, struct tevent_req
);
3522 struct lock_ntcancel_state
*state
= tevent_req_data(
3523 req
, struct lock_ntcancel_state
);
3526 ok
= tevent_wakeup_recv(subreq
);
3527 TALLOC_FREE(subreq
);
3529 tevent_req_oom(req
);
3533 ok
= tevent_req_cancel(state
->subreq
);
3535 d_fprintf(stderr
, "Could not cancel subreq\n");
3536 tevent_req_oom(req
);
3541 static void lock_ntcancel_done(struct tevent_req
*subreq
)
3543 struct tevent_req
*req
= tevent_req_callback_data(
3544 subreq
, struct tevent_req
);
3545 struct lock_ntcancel_state
*state
= tevent_req_data(
3546 req
, struct lock_ntcancel_state
);
3550 status
= cli_lockingx_recv(subreq
);
3551 TALLOC_FREE(subreq
);
3553 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
3554 d_printf("cli_lockingx returned %s\n", nt_errstr(status
));
3555 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
3559 elapsed
= timeval_elapsed(&state
->start
);
3562 d_printf("cli_lockingx was too slow, cancel did not work\n");
3563 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
3567 tevent_req_done(req
);
3570 static NTSTATUS
lock_ntcancel_recv(struct tevent_req
*req
)
3572 return tevent_req_simple_recv_ntstatus(req
);
3575 static bool run_locktest13(int dummy
)
3577 struct tevent_context
*ev
= NULL
;
3578 struct tevent_req
*req
= NULL
;
3579 struct cli_state
*cli
= NULL
;
3580 const char fname
[] = "\\lockt13.lck";
3581 uint16_t fnum1
, fnum2
;
3587 printf("starting locktest13\n");
3589 ev
= samba_tevent_context_init(NULL
);
3591 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
3595 ok
= torture_open_connection(&cli
, 0);
3599 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3601 status
= cli_openx(cli
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum1
);
3602 if (!NT_STATUS_IS_OK(status
)) {
3604 "cli_openx failed: %s\n",
3609 status
= cli_openx(cli
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum2
);
3610 if (!NT_STATUS_IS_OK(status
)) {
3612 "cli_openx failed: %s\n",
3617 status
= cli_writeall(cli
, fnum1
, 0, &data
, 0, sizeof(data
), NULL
);
3618 if (!NT_STATUS_IS_OK(status
)) {
3620 "cli_writeall failed: %s\n",
3625 status
= cli_locktype(
3626 cli
, fnum1
, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK
);
3627 if (!NT_STATUS_IS_OK(status
)) {
3629 "cli_locktype failed: %s\n",
3634 req
= lock_ntcancel_send(ev
, ev
, cli
, fnum2
);
3636 d_fprintf(stderr
, "lock_ntcancel_send failed\n");
3640 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
3642 d_fprintf(stderr
, "tevent_req_poll_ntstatus failed\n");
3646 if (!NT_STATUS_IS_OK(status
)) {
3648 "tevent_req_poll_ntstatus returned %s\n",
3653 status
= lock_ntcancel_recv(req
);
3654 if (!NT_STATUS_IS_OK(status
)) {
3656 "lock_ntcancel returned %s\n",
3664 torture_close_connection(cli
);
3670 test whether fnums and tids open on one VC are available on another (a major
3673 static bool run_fdpasstest(int dummy
)
3675 struct cli_state
*cli1
, *cli2
;
3676 const char *fname
= "\\fdpass.tst";
3681 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
3684 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
3685 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
3687 printf("starting fdpasstest\n");
3689 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3691 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
3693 if (!NT_STATUS_IS_OK(status
)) {
3694 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
3698 status
= cli_writeall(cli1
, fnum1
, 0, (const uint8_t *)"hello world\n", 0,
3700 if (!NT_STATUS_IS_OK(status
)) {
3701 printf("write failed (%s)\n", nt_errstr(status
));
3705 cli_state_set_uid(cli2
, cli_state_get_uid(cli1
));
3706 cli_state_set_tid(cli2
, cli_state_get_tid(cli1
));
3707 cli_setpid(cli2
, cli_getpid(cli1
));
3709 if (test_cli_read(cli2
, fnum1
, buf
, 0, 13, NULL
, 13)) {
3710 printf("read succeeded! nasty security hole [%s]\n", buf
);
3714 cli_close(cli1
, fnum1
);
3715 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3717 torture_close_connection(cli1
);
3718 torture_close_connection(cli2
);
3720 printf("finished fdpasstest\n");
3724 static bool run_fdsesstest(int dummy
)
3726 struct cli_state
*cli
;
3728 uint16_t saved_vuid
;
3730 uint32_t saved_cnum
;
3731 const char *fname
= "\\fdsess.tst";
3732 const char *fname1
= "\\fdsess1.tst";
3739 if (!torture_open_connection(&cli
, 0))
3741 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3743 if (!torture_cli_session_setup2(cli
, &new_vuid
))
3746 saved_cnum
= cli_state_get_tid(cli
);
3747 if (!NT_STATUS_IS_OK(cli_tree_connect(cli
, share
, "?????", NULL
)))
3749 new_cnum
= cli_state_get_tid(cli
);
3750 cli_state_set_tid(cli
, saved_cnum
);
3752 printf("starting fdsesstest\n");
3754 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3755 cli_unlink(cli
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3757 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
3758 if (!NT_STATUS_IS_OK(status
)) {
3759 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
3763 status
= cli_writeall(cli
, fnum1
, 0, (const uint8_t *)"hello world\n", 0, 13,
3765 if (!NT_STATUS_IS_OK(status
)) {
3766 printf("write failed (%s)\n", nt_errstr(status
));
3770 saved_vuid
= cli_state_get_uid(cli
);
3771 cli_state_set_uid(cli
, new_vuid
);
3773 if (test_cli_read(cli
, fnum1
, buf
, 0, 13, NULL
, 13)) {
3774 printf("read succeeded with different vuid! "
3775 "nasty security hole [%s]\n", buf
);
3778 /* Try to open a file with different vuid, samba cnum. */
3779 if (NT_STATUS_IS_OK(cli_openx(cli
, fname1
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum2
))) {
3780 printf("create with different vuid, same cnum succeeded.\n");
3781 cli_close(cli
, fnum2
);
3782 cli_unlink(cli
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3784 printf("create with different vuid, same cnum failed.\n");
3785 printf("This will cause problems with service clients.\n");
3789 cli_state_set_uid(cli
, saved_vuid
);
3791 /* Try with same vuid, different cnum. */
3792 cli_state_set_tid(cli
, new_cnum
);
3794 if (test_cli_read(cli
, fnum1
, buf
, 0, 13, NULL
, 13)) {
3795 printf("read succeeded with different cnum![%s]\n", buf
);
3799 cli_state_set_tid(cli
, saved_cnum
);
3800 cli_close(cli
, fnum1
);
3801 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3803 torture_close_connection(cli
);
3805 printf("finished fdsesstest\n");
3810 This test checks that
3812 1) the server does not allow an unlink on a file that is open
3814 static bool run_unlinktest(int dummy
)
3816 struct cli_state
*cli
;
3817 const char *fname
= "\\unlink.tst";
3819 bool correct
= True
;
3822 if (!torture_open_connection(&cli
, 0)) {
3826 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3828 printf("starting unlink test\n");
3830 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3834 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
3835 if (!NT_STATUS_IS_OK(status
)) {
3836 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
3840 status
= cli_unlink(cli
, fname
,
3841 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3842 if (NT_STATUS_IS_OK(status
)) {
3843 printf("error: server allowed unlink on an open file\n");
3846 correct
= check_error(__LINE__
, status
, ERRDOS
, ERRbadshare
,
3847 NT_STATUS_SHARING_VIOLATION
);
3850 cli_close(cli
, fnum
);
3851 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3853 if (!torture_close_connection(cli
)) {
3857 printf("unlink test finished\n");
3864 test how many open files this server supports on the one socket
3866 static bool run_maxfidtest(int dummy
)
3868 struct cli_state
*cli
;
3870 uint16_t fnums
[0x11000];
3873 bool correct
= True
;
3879 printf("failed to connect\n");
3883 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3885 for (i
=0; i
<0x11000; i
++) {
3886 slprintf(fname
,sizeof(fname
)-1,"\\maxfid.%d.%d", i
,(int)getpid());
3887 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
,
3889 if (!NT_STATUS_IS_OK(status
)) {
3890 printf("open of %s failed (%s)\n",
3891 fname
, nt_errstr(status
));
3892 printf("maximum fnum is %d\n", i
);
3900 printf("cleaning up\n");
3902 slprintf(fname
,sizeof(fname
)-1,"\\maxfid.%d.%d", i
,(int)getpid());
3903 cli_close(cli
, fnums
[i
]);
3905 status
= cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3906 if (!NT_STATUS_IS_OK(status
)) {
3907 printf("unlink of %s failed (%s)\n",
3908 fname
, nt_errstr(status
));
3915 printf("maxfid test finished\n");
3916 if (!torture_close_connection(cli
)) {
3922 /* generate a random buffer */
3923 static void rand_buf(char *buf
, int len
)
3926 *buf
= (char)sys_random();
3931 /* send smb negprot commands, not reading the response */
3932 static bool run_negprot_nowait(int dummy
)
3934 struct tevent_context
*ev
;
3936 struct cli_state
*cli
;
3937 bool correct
= True
;
3939 printf("starting negprot nowait test\n");
3941 ev
= samba_tevent_context_init(talloc_tos());
3946 if (!(cli
= open_nbt_connection())) {
3951 for (i
=0;i
<50000;i
++) {
3952 struct tevent_req
*req
;
3954 req
= smbXcli_negprot_send(
3967 if (!tevent_req_poll(req
, ev
)) {
3968 d_fprintf(stderr
, "tevent_req_poll failed: %s\n",
3976 if (torture_close_connection(cli
)) {
3980 printf("finished negprot nowait test\n");
3985 /* send smb negprot commands, not reading the response */
3986 static bool run_bad_nbt_session(int dummy
)
3988 struct nmb_name called
, calling
;
3989 struct sockaddr_storage ss
;
3994 printf("starting bad nbt session test\n");
3996 make_nmb_name(&calling
, myname
, 0x0);
3997 make_nmb_name(&called
, host
, 0x20);
3999 if (!resolve_name(host
, &ss
, 0x20, true)) {
4000 d_fprintf(stderr
, "Could not resolve name %s\n", host
);
4004 status
= open_socket_out(&ss
, NBT_SMB_PORT
, 10000, &fd
);
4005 if (!NT_STATUS_IS_OK(status
)) {
4006 d_fprintf(stderr
, "open_socket_out failed: %s\n",
4011 ret
= cli_bad_session_request(fd
, &calling
, &called
);
4014 d_fprintf(stderr
, "open_socket_out failed: %s\n",
4019 printf("finished bad nbt session test\n");
4023 /* send random IPC commands */
4024 static bool run_randomipc(int dummy
)
4026 char *rparam
= NULL
;
4028 unsigned int rdrcnt
,rprcnt
;
4030 int api
, param_len
, i
;
4031 struct cli_state
*cli
;
4032 bool correct
= True
;
4035 printf("starting random ipc test\n");
4037 if (!torture_open_connection(&cli
, 0)) {
4041 for (i
=0;i
<count
;i
++) {
4042 api
= sys_random() % 500;
4043 param_len
= (sys_random() % 64);
4045 rand_buf(param
, param_len
);
4050 param
, param_len
, 8,
4051 NULL
, 0, CLI_BUFFER_SIZE
,
4055 printf("%d/%d\r", i
,count
);
4058 printf("%d/%d\n", i
, count
);
4060 if (!torture_close_connection(cli
)) {
4067 printf("finished random ipc test\n");
4074 static void browse_callback(const char *sname
, uint32_t stype
,
4075 const char *comment
, void *state
)
4077 printf("\t%20.20s %08x %s\n", sname
, stype
, comment
);
4083 This test checks the browse list code
4086 static bool run_browsetest(int dummy
)
4088 static struct cli_state
*cli
;
4089 bool correct
= True
;
4091 printf("starting browse test\n");
4093 if (!torture_open_connection(&cli
, 0)) {
4097 printf("domain list:\n");
4098 cli_NetServerEnum(cli
, cli
->server_domain
,
4099 SV_TYPE_DOMAIN_ENUM
,
4100 browse_callback
, NULL
);
4102 printf("machine list:\n");
4103 cli_NetServerEnum(cli
, cli
->server_domain
,
4105 browse_callback
, NULL
);
4107 if (!torture_close_connection(cli
)) {
4111 printf("browse test finished\n");
4117 static bool check_attributes(struct cli_state
*cli
,
4119 uint32_t expected_attrs
)
4122 NTSTATUS status
= cli_getatr(cli
,
4127 if (!NT_STATUS_IS_OK(status
)) {
4128 printf("cli_getatr failed with %s\n",
4132 if (attrs
!= expected_attrs
) {
4133 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4134 (unsigned int)attrs
,
4135 (unsigned int)expected_attrs
);
4142 This checks how the getatr calls works
4144 static bool run_attrtest(int dummy
)
4146 struct cli_state
*cli
;
4149 const char *fname
= "\\attrib123456789.tst";
4150 bool correct
= True
;
4153 printf("starting attrib test\n");
4155 if (!torture_open_connection(&cli
, 0)) {
4159 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4160 status
= cli_unlink(cli
, fname
, 0x20000);
4161 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
4166 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4167 cli_openx(cli
, fname
,
4168 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4169 cli_close(cli
, fnum
);
4171 status
= cli_getatr(cli
, fname
, NULL
, NULL
, &t
);
4172 if (!NT_STATUS_IS_OK(status
)) {
4173 printf("getatr failed (%s)\n", nt_errstr(status
));
4177 if (labs(t
- time(NULL
)) > 60*60*24*10) {
4178 printf("ERROR: SMBgetatr bug. time is %s",
4184 t2
= t
-60*60*24; /* 1 day ago */
4186 /* Ensure we can't set with out-of-range (unknown) attribute. */
4187 status
= cli_setatr(cli
, fname
, 0x20000, t2
);
4188 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
4193 status
= cli_setatr(cli
, fname
, 0, t2
);
4194 if (!NT_STATUS_IS_OK(status
)) {
4195 printf("setatr failed (%s)\n", nt_errstr(status
));
4199 status
= cli_getatr(cli
, fname
, NULL
, NULL
, &t
);
4200 if (!NT_STATUS_IS_OK(status
)) {
4201 printf("getatr failed (%s)\n", nt_errstr(status
));
4206 printf("ERROR: getatr/setatr bug. times are\n%s",
4208 printf("%s", ctime(&t2
));
4212 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4214 /* Check cli_setpathinfo_ext() */
4215 /* Re-create the file. */
4216 status
= cli_openx(cli
, fname
,
4217 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4218 if (!NT_STATUS_IS_OK(status
)) {
4219 printf("Failed to recreate %s (%s)\n",
4220 fname
, nt_errstr(status
));
4223 cli_close(cli
, fnum
);
4225 status
= cli_setpathinfo_ext(
4228 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* create */
4229 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* access */
4230 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* write */
4231 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* change */
4232 FILE_ATTRIBUTE_SYSTEM
|
4233 FILE_ATTRIBUTE_HIDDEN
|
4234 FILE_ATTRIBUTE_READONLY
);
4235 if (!NT_STATUS_IS_OK(status
)) {
4236 printf("cli_setpathinfo_ext failed with %s\n",
4241 /* Check attributes are correct. */
4242 correct
= check_attributes(cli
,
4244 FILE_ATTRIBUTE_SYSTEM
|
4245 FILE_ATTRIBUTE_HIDDEN
|
4246 FILE_ATTRIBUTE_READONLY
);
4247 if (correct
== false) {
4251 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4252 status
= cli_setpathinfo_ext(
4255 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* create */
4256 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* access */
4257 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* write */
4258 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* change */
4259 FILE_ATTRIBUTE_NORMAL
);
4260 if (!NT_STATUS_IS_OK(status
)) {
4261 printf("cli_setpathinfo_ext failed with %s\n",
4266 /* Check attributes are correct. */
4267 correct
= check_attributes(cli
,
4269 FILE_ATTRIBUTE_SYSTEM
|
4270 FILE_ATTRIBUTE_HIDDEN
|
4271 FILE_ATTRIBUTE_READONLY
);
4272 if (correct
== false) {
4276 /* Setting to (uint16_t)-1 should also be ignored. */
4277 status
= cli_setpathinfo_ext(
4280 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* create */
4281 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* access */
4282 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* write */
4283 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* change */
4285 if (!NT_STATUS_IS_OK(status
)) {
4286 printf("cli_setpathinfo_ext failed with %s\n",
4291 /* Check attributes are correct. */
4292 correct
= check_attributes(cli
,
4294 FILE_ATTRIBUTE_SYSTEM
|
4295 FILE_ATTRIBUTE_HIDDEN
|
4296 FILE_ATTRIBUTE_READONLY
);
4297 if (correct
== false) {
4301 /* Setting to 0 should clear them all. */
4302 status
= cli_setpathinfo_ext(
4305 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* create */
4306 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* access */
4307 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* write */
4308 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* change */
4310 if (!NT_STATUS_IS_OK(status
)) {
4311 printf("cli_setpathinfo_ext failed with %s\n",
4316 /* Check attributes are correct. */
4317 correct
= check_attributes(cli
,
4319 FILE_ATTRIBUTE_NORMAL
);
4320 if (correct
== false) {
4328 FILE_ATTRIBUTE_SYSTEM
|
4329 FILE_ATTRIBUTE_HIDDEN
|
4330 FILE_ATTRIBUTE_READONLY
);
4332 if (!torture_close_connection(cli
)) {
4336 printf("attrib test finished\n");
4341 static NTSTATUS
cli_qfilename(
4342 struct cli_state
*cli
,
4344 TALLOC_CTX
*mem_ctx
,
4347 uint16_t recv_flags2
;
4354 status
= cli_qfileinfo(talloc_tos(), cli
, fnum
,
4355 SMB_QUERY_FILE_NAME_INFO
,
4356 4, CLI_BUFFER_SIZE
, &recv_flags2
,
4357 &rdata
, &num_rdata
);
4358 if (!NT_STATUS_IS_OK(status
)) {
4362 namelen
= IVAL(rdata
, 0);
4363 if (namelen
> (num_rdata
- 4)) {
4365 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
4368 pull_string_talloc(mem_ctx
,
4369 (const char *)rdata
,
4376 status
= map_nt_error_from_unix(errno
);
4383 return NT_STATUS_OK
;
4387 This checks a couple of trans2 calls
4389 static bool run_trans2test(int dummy
)
4391 struct cli_state
*cli
;
4394 time_t c_time
, a_time
, m_time
;
4395 struct timespec c_time_ts
, a_time_ts
, m_time_ts
, w_time_ts
, m_time2_ts
;
4396 const char *fname
= "\\trans2.tst";
4397 const char *dname
= "\\trans2";
4398 const char *fname2
= "\\trans2\\trans2.tst";
4400 bool correct
= True
;
4405 printf("starting trans2 test\n");
4407 if (!torture_open_connection(&cli
, 0)) {
4411 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4412 /* Ensure ino is zero, SMB2 gets a real one. */
4415 /* Ensure ino is -1, SMB1 never gets a real one. */
4419 status
= cli_get_fs_attr_info(cli
, &fs_attr
);
4420 if (!NT_STATUS_IS_OK(status
)) {
4421 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4426 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4427 cli_openx(cli
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4428 status
= cli_qfileinfo_basic(cli
, fnum
, NULL
, &size
, &c_time_ts
,
4429 &a_time_ts
, &w_time_ts
, &m_time_ts
, NULL
);
4430 if (!NT_STATUS_IS_OK(status
)) {
4431 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status
));
4435 status
= cli_qfilename(cli
, fnum
, talloc_tos(), &pname
);
4436 if (!NT_STATUS_IS_OK(status
)) {
4437 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status
));
4440 else if (strcmp(pname
, fname
)) {
4441 printf("qfilename gave different name? [%s] [%s]\n",
4446 cli_close(cli
, fnum
);
4450 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4451 status
= cli_openx(cli
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
,
4453 if (!NT_STATUS_IS_OK(status
)) {
4454 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4457 cli_close(cli
, fnum
);
4459 status
= cli_qpathinfo1(cli
, fname
, &c_time
, &a_time
, &m_time
, &size
,
4461 if (!NT_STATUS_IS_OK(status
)) {
4462 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status
));
4465 time_t t
= time(NULL
);
4467 if (c_time
!= m_time
) {
4468 printf("create time=%s", ctime(&c_time
));
4469 printf("modify time=%s", ctime(&m_time
));
4470 printf("This system appears to have sticky create times\n");
4472 if ((labs(a_time
- t
) > 60) && (a_time
% (60*60) == 0)) {
4473 printf("access time=%s", ctime(&a_time
));
4474 printf("This system appears to set a midnight access time\n");
4478 if (labs(m_time
- t
) > 60*60*24*7) {
4479 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time
));
4485 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4486 cli_openx(cli
, fname
,
4487 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4488 cli_close(cli
, fnum
);
4489 status
= cli_qpathinfo2(cli
, fname
, &c_time_ts
, &a_time_ts
, &w_time_ts
,
4490 &m_time_ts
, &size
, NULL
, &ino
);
4491 if (!NT_STATUS_IS_OK(status
)) {
4492 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status
));
4495 if (w_time_ts
.tv_sec
< 60*60*24*2) {
4496 printf("write time=%s", ctime(&w_time_ts
.tv_sec
));
4497 printf("This system appears to set a initial 0 write time\n");
4500 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4501 /* SMB2 should always return an inode. */
4503 printf("SMB2 bad inode (0)\n");
4507 /* SMB1 must always return zero here. */
4509 printf("SMB1 bad inode (!0)\n");
4515 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4518 /* check if the server updates the directory modification time
4519 when creating a new file */
4520 status
= cli_mkdir(cli
, dname
);
4521 if (!NT_STATUS_IS_OK(status
)) {
4522 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status
));
4526 status
= cli_qpathinfo2(cli
, "\\trans2\\", &c_time_ts
, &a_time_ts
,
4527 &w_time_ts
, &m_time_ts
, &size
, NULL
, NULL
);
4528 if (!NT_STATUS_IS_OK(status
)) {
4529 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status
));
4533 cli_openx(cli
, fname2
,
4534 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4535 cli_writeall(cli
, fnum
, 0, (uint8_t *)&fnum
, 0, sizeof(fnum
), NULL
);
4536 cli_close(cli
, fnum
);
4537 status
= cli_qpathinfo2(cli
, "\\trans2\\", &c_time_ts
, &a_time_ts
,
4538 &w_time_ts
, &m_time2_ts
, &size
, NULL
, NULL
);
4539 if (!NT_STATUS_IS_OK(status
)) {
4540 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status
));
4543 if (memcmp(&m_time_ts
, &m_time2_ts
, sizeof(struct timespec
))
4545 printf("This system does not update directory modification times\n");
4549 cli_unlink(cli
, fname2
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4550 cli_rmdir(cli
, dname
);
4552 if (!torture_close_connection(cli
)) {
4556 printf("trans2 test finished\n");
4562 This checks new W2K calls.
4565 static NTSTATUS
new_trans(struct cli_state
*pcli
, int fnum
, int level
)
4567 uint8_t *buf
= NULL
;
4571 status
= cli_qfileinfo(talloc_tos(), pcli
, fnum
, level
, 0,
4572 CLI_BUFFER_SIZE
, NULL
, &buf
, &len
);
4573 if (!NT_STATUS_IS_OK(status
)) {
4574 printf("ERROR: qfileinfo (%d) failed (%s)\n", level
,
4577 printf("qfileinfo: level %d, len = %u\n", level
, len
);
4578 dump_data(0, (uint8_t *)buf
, len
);
4585 static bool run_w2ktest(int dummy
)
4587 struct cli_state
*cli
;
4589 const char *fname
= "\\w2ktest\\w2k.tst";
4591 bool correct
= True
;
4593 printf("starting w2k test\n");
4595 if (!torture_open_connection(&cli
, 0)) {
4599 cli_openx(cli
, fname
,
4600 O_RDWR
| O_CREAT
, DENY_NONE
, &fnum
);
4602 for (level
= 1004; level
< 1040; level
++) {
4603 new_trans(cli
, fnum
, level
);
4606 cli_close(cli
, fnum
);
4608 if (!torture_close_connection(cli
)) {
4612 printf("w2k test finished\n");
4619 this is a harness for some oplock tests
4621 static bool run_oplock1(int dummy
)
4623 struct cli_state
*cli1
;
4624 const char *fname
= "\\lockt1.lck";
4626 bool correct
= True
;
4629 printf("starting oplock test 1\n");
4631 if (!torture_open_connection(&cli1
, 0)) {
4635 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4637 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
4639 cli1
->use_oplocks
= True
;
4641 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
4643 if (!NT_STATUS_IS_OK(status
)) {
4644 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4648 cli1
->use_oplocks
= False
;
4650 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4651 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4653 status
= cli_close(cli1
, fnum1
);
4654 if (!NT_STATUS_IS_OK(status
)) {
4655 printf("close2 failed (%s)\n", nt_errstr(status
));
4659 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4660 if (!NT_STATUS_IS_OK(status
)) {
4661 printf("unlink failed (%s)\n", nt_errstr(status
));
4665 if (!torture_close_connection(cli1
)) {
4669 printf("finished oplock test 1\n");
4674 static bool run_oplock2(int dummy
)
4676 struct cli_state
*cli1
, *cli2
;
4677 const char *fname
= "\\lockt2.lck";
4678 uint16_t fnum1
, fnum2
;
4679 int saved_use_oplocks
= use_oplocks
;
4681 bool correct
= True
;
4682 volatile bool *shared_correct
;
4686 shared_correct
= (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4687 *shared_correct
= True
;
4689 use_level_II_oplocks
= True
;
4692 printf("starting oplock test 2\n");
4694 if (!torture_open_connection(&cli1
, 0)) {
4695 use_level_II_oplocks
= False
;
4696 use_oplocks
= saved_use_oplocks
;
4700 if (!torture_open_connection(&cli2
, 1)) {
4701 use_level_II_oplocks
= False
;
4702 use_oplocks
= saved_use_oplocks
;
4706 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4708 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
4709 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
4711 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
4713 if (!NT_STATUS_IS_OK(status
)) {
4714 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4718 /* Don't need the globals any more. */
4719 use_level_II_oplocks
= False
;
4720 use_oplocks
= saved_use_oplocks
;
4724 status
= cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
4725 if (!NT_STATUS_IS_OK(status
)) {
4726 printf("second open of %s failed (%s)\n", fname
, nt_errstr(status
));
4727 *shared_correct
= False
;
4733 status
= cli_close(cli2
, fnum2
);
4734 if (!NT_STATUS_IS_OK(status
)) {
4735 printf("close2 failed (%s)\n", nt_errstr(status
));
4736 *shared_correct
= False
;
4744 /* Ensure cli1 processes the break. Empty file should always return 0
4746 status
= cli_read(cli1
, fnum1
, buf
, 0, 4, &nread
);
4747 if (!NT_STATUS_IS_OK(status
)) {
4748 printf("read on fnum1 failed (%s)\n", nt_errstr(status
));
4750 } else if (nread
!= 0) {
4751 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4752 (unsigned long)nread
, 0);
4756 /* Should now be at level II. */
4757 /* Test if sending a write locks causes a break to none. */
4758 status
= cli_lock32(cli1
, fnum1
, 0, 4, 0, READ_LOCK
);
4759 if (!NT_STATUS_IS_OK(status
)) {
4760 printf("lock failed (%s)\n", nt_errstr(status
));
4764 cli_unlock(cli1
, fnum1
, 0, 4);
4768 status
= cli_lock32(cli1
, fnum1
, 0, 4, 0, WRITE_LOCK
);
4769 if (!NT_STATUS_IS_OK(status
)) {
4770 printf("lock failed (%s)\n", nt_errstr(status
));
4774 cli_unlock(cli1
, fnum1
, 0, 4);
4778 cli_read(cli1
, fnum1
, buf
, 0, 4, NULL
);
4780 status
= cli_close(cli1
, fnum1
);
4781 if (!NT_STATUS_IS_OK(status
)) {
4782 printf("close1 failed (%s)\n", nt_errstr(status
));
4788 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4789 if (!NT_STATUS_IS_OK(status
)) {
4790 printf("unlink failed (%s)\n", nt_errstr(status
));
4794 if (!torture_close_connection(cli1
)) {
4798 if (!*shared_correct
) {
4802 printf("finished oplock test 2\n");
4807 struct oplock4_state
{
4808 struct tevent_context
*ev
;
4809 struct cli_state
*cli
;
4814 static void oplock4_got_break(struct tevent_req
*req
);
4815 static void oplock4_got_open(struct tevent_req
*req
);
4817 static bool run_oplock4(int dummy
)
4819 struct tevent_context
*ev
;
4820 struct cli_state
*cli1
, *cli2
;
4821 struct tevent_req
*oplock_req
, *open_req
;
4822 const char *fname
= "\\lockt4.lck";
4823 const char *fname_ln
= "\\lockt4_ln.lck";
4824 uint16_t fnum1
, fnum2
;
4825 int saved_use_oplocks
= use_oplocks
;
4827 bool correct
= true;
4831 struct oplock4_state
*state
;
4833 printf("starting oplock test 4\n");
4835 if (!torture_open_connection(&cli1
, 0)) {
4836 use_level_II_oplocks
= false;
4837 use_oplocks
= saved_use_oplocks
;
4841 if (!torture_open_connection(&cli2
, 1)) {
4842 use_level_II_oplocks
= false;
4843 use_oplocks
= saved_use_oplocks
;
4847 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4848 cli_unlink(cli1
, fname_ln
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4850 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
4851 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
4853 /* Create the file. */
4854 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
4856 if (!NT_STATUS_IS_OK(status
)) {
4857 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4861 status
= cli_close(cli1
, fnum1
);
4862 if (!NT_STATUS_IS_OK(status
)) {
4863 printf("close1 failed (%s)\n", nt_errstr(status
));
4867 /* Now create a hardlink. */
4868 status
= cli_hardlink(cli1
, fname
, fname_ln
);
4869 if (!NT_STATUS_IS_OK(status
)) {
4870 printf("nt hardlink failed (%s)\n", nt_errstr(status
));
4874 /* Prove that opening hardlinks cause deny modes to conflict. */
4875 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_ALL
, &fnum1
);
4876 if (!NT_STATUS_IS_OK(status
)) {
4877 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4881 status
= cli_openx(cli1
, fname_ln
, O_RDWR
, DENY_NONE
, &fnum2
);
4882 if (NT_STATUS_IS_OK(status
)) {
4883 printf("open of %s succeeded - should fail with sharing violation.\n",
4888 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
4889 printf("open of %s should fail with sharing violation. Got %s\n",
4890 fname_ln
, nt_errstr(status
));
4894 status
= cli_close(cli1
, fnum1
);
4895 if (!NT_STATUS_IS_OK(status
)) {
4896 printf("close1 failed (%s)\n", nt_errstr(status
));
4900 cli1
->use_oplocks
= true;
4901 cli2
->use_oplocks
= true;
4903 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
4904 if (!NT_STATUS_IS_OK(status
)) {
4905 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4909 ev
= samba_tevent_context_init(talloc_tos());
4911 printf("tevent_context_init failed\n");
4915 state
= talloc(ev
, struct oplock4_state
);
4916 if (state
== NULL
) {
4917 printf("talloc failed\n");
4922 state
->got_break
= &got_break
;
4923 state
->fnum2
= &fnum2
;
4925 oplock_req
= cli_smb_oplock_break_waiter_send(
4926 talloc_tos(), ev
, cli1
);
4927 if (oplock_req
== NULL
) {
4928 printf("cli_smb_oplock_break_waiter_send failed\n");
4931 tevent_req_set_callback(oplock_req
, oplock4_got_break
, state
);
4933 open_req
= cli_openx_send(
4934 talloc_tos(), ev
, cli2
, fname_ln
, O_RDWR
, DENY_NONE
);
4935 if (open_req
== NULL
) {
4936 printf("cli_openx_send failed\n");
4939 tevent_req_set_callback(open_req
, oplock4_got_open
, state
);
4944 while (!got_break
|| fnum2
== 0xffff) {
4946 ret
= tevent_loop_once(ev
);
4948 printf("tevent_loop_once failed: %s\n",
4954 status
= cli_close(cli2
, fnum2
);
4955 if (!NT_STATUS_IS_OK(status
)) {
4956 printf("close2 failed (%s)\n", nt_errstr(status
));
4960 status
= cli_close(cli1
, fnum1
);
4961 if (!NT_STATUS_IS_OK(status
)) {
4962 printf("close1 failed (%s)\n", nt_errstr(status
));
4966 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4967 if (!NT_STATUS_IS_OK(status
)) {
4968 printf("unlink failed (%s)\n", nt_errstr(status
));
4972 status
= cli_unlink(cli1
, fname_ln
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4973 if (!NT_STATUS_IS_OK(status
)) {
4974 printf("unlink failed (%s)\n", nt_errstr(status
));
4978 if (!torture_close_connection(cli1
)) {
4986 printf("finished oplock test 4\n");
4991 static void oplock4_got_break(struct tevent_req
*req
)
4993 struct oplock4_state
*state
= tevent_req_callback_data(
4994 req
, struct oplock4_state
);
4999 status
= cli_smb_oplock_break_waiter_recv(req
, &fnum
, &level
);
5001 if (!NT_STATUS_IS_OK(status
)) {
5002 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5006 *state
->got_break
= true;
5008 req
= cli_oplock_ack_send(state
, state
->ev
, state
->cli
, fnum
,
5011 printf("cli_oplock_ack_send failed\n");
5016 static void oplock4_got_open(struct tevent_req
*req
)
5018 struct oplock4_state
*state
= tevent_req_callback_data(
5019 req
, struct oplock4_state
);
5022 status
= cli_openx_recv(req
, state
->fnum2
);
5023 if (!NT_STATUS_IS_OK(status
)) {
5024 printf("cli_openx_recv returned %s\n", nt_errstr(status
));
5025 *state
->fnum2
= 0xffff;
5029 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5031 struct oplock5_state
{
5036 * Async open the file that has a kernel oplock, do an echo to get
5037 * that 100% across, close the file to signal to the child fd that the
5038 * oplock can be dropped, wait for the open reply.
5041 static void oplock5_opened(struct tevent_req
*subreq
);
5042 static void oplock5_pong(struct tevent_req
*subreq
);
5043 static void oplock5_timedout(struct tevent_req
*subreq
);
5045 static struct tevent_req
*oplock5_send(
5046 TALLOC_CTX
*mem_ctx
,
5047 struct tevent_context
*ev
,
5048 struct cli_state
*cli
,
5052 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5053 struct oplock5_state
*state
= NULL
;
5054 static uint8_t data
= 0;
5056 req
= tevent_req_create(mem_ctx
, &state
, struct oplock5_state
);
5060 state
->pipe_down_fd
= pipe_down_fd
;
5062 subreq
= cli_ntcreate_send(
5068 SEC_FILE_READ_DATA
, /* DesiredAccess */
5069 FILE_ATTRIBUTE_NORMAL
, /* FileAttributes */
5070 FILE_SHARE_WRITE
|FILE_SHARE_READ
, /* ShareAccess */
5071 FILE_OPEN
, /* CreateDisposition */
5072 FILE_NON_DIRECTORY_FILE
, /* CreateOptions */
5073 0, /* Impersonation */
5074 0); /* SecurityFlags */
5075 if (tevent_req_nomem(subreq
, req
)) {
5076 return tevent_req_post(req
, ev
);
5078 tevent_req_set_callback(subreq
, oplock5_opened
, req
);
5080 subreq
= cli_echo_send(
5085 (DATA_BLOB
) { .data
= &data
, .length
= sizeof(data
) });
5086 if (tevent_req_nomem(subreq
, req
)) {
5087 return tevent_req_post(req
, ev
);
5089 tevent_req_set_callback(subreq
, oplock5_pong
, req
);
5091 subreq
= tevent_wakeup_send(state
, ev
, timeval_current_ofs(20, 0));
5092 if (tevent_req_nomem(subreq
, req
)) {
5093 return tevent_req_post(req
, ev
);
5095 tevent_req_set_callback(subreq
, oplock5_timedout
, req
);
5100 static void oplock5_opened(struct tevent_req
*subreq
)
5102 struct tevent_req
*req
= tevent_req_callback_data(
5103 subreq
, struct tevent_req
);
5107 status
= cli_ntcreate_recv(subreq
, &fnum
, NULL
);
5108 TALLOC_FREE(subreq
);
5109 if (tevent_req_nterror(req
, status
)) {
5112 tevent_req_done(req
);
5115 static void oplock5_pong(struct tevent_req
*subreq
)
5117 struct tevent_req
*req
= tevent_req_callback_data(
5118 subreq
, struct tevent_req
);
5119 struct oplock5_state
*state
= tevent_req_data(
5120 req
, struct oplock5_state
);
5123 status
= cli_echo_recv(subreq
);
5124 TALLOC_FREE(subreq
);
5125 if (tevent_req_nterror(req
, status
)) {
5129 close(state
->pipe_down_fd
);
5132 static void oplock5_timedout(struct tevent_req
*subreq
)
5134 struct tevent_req
*req
= tevent_req_callback_data(
5135 subreq
, struct tevent_req
);
5138 ok
= tevent_wakeup_recv(subreq
);
5139 TALLOC_FREE(subreq
);
5141 tevent_req_oom(req
);
5144 tevent_req_nterror(req
, NT_STATUS_TIMEOUT
);
5147 static NTSTATUS
oplock5_recv(struct tevent_req
*req
)
5149 return tevent_req_simple_recv_ntstatus(req
);
5152 static bool run_oplock5(int dummy
)
5154 struct tevent_context
*ev
= NULL
;
5155 struct tevent_req
*req
= NULL
;
5156 struct cli_state
*cli
= NULL
;
5157 const char *fname
= "oplock5.txt";
5158 int pipe_down
[2], pipe_up
[2];
5165 printf("starting oplock5\n");
5167 if (local_path
== NULL
) {
5168 d_fprintf(stderr
, "oplock5 must be given a local path via "
5169 "-l <localpath>\n");
5173 ret
= pipe(pipe_down
);
5175 d_fprintf(stderr
, "pipe() failed: %s\n", strerror(errno
));
5178 ret
= pipe(pipe_up
);
5180 d_fprintf(stderr
, "pipe() failed: %s\n", strerror(errno
));
5185 if (child_pid
== -1) {
5186 d_fprintf(stderr
, "fork() failed: %s\n", strerror(errno
));
5190 if (child_pid
== 0) {
5191 char *local_file
= NULL
;
5194 close(pipe_down
[1]);
5197 local_file
= talloc_asprintf(
5198 talloc_tos(), "%s/%s", local_path
, fname
);
5199 if (local_file
== 0) {
5203 fd
= open(local_file
, O_RDWR
|O_CREAT
, 0644);
5206 "open(%s) in child failed: %s\n",
5213 signal(SIGIO
, SIG_IGN
);
5215 ret
= fcntl(fd
, F_SETLEASE
, F_WRLCK
);
5218 "SETLEASE in child failed: %s\n",
5225 ret
= sys_write(pipe_up
[1], &c
, sizeof(c
));
5228 "sys_write failed: %s\n",
5232 ret
= sys_read(pipe_down
[0], &c
, sizeof(c
));
5235 "sys_read failed: %s\n",
5243 close(pipe_down
[0]);
5245 ret
= sys_read(pipe_up
[0], &c
, sizeof(c
));
5248 "sys_read failed: %s\n",
5253 d_fprintf(stderr
, "got error code %"PRIu8
"\n", c
);
5257 ok
= torture_open_connection(&cli
, 0);
5259 d_fprintf(stderr
, "torture_open_connection failed\n");
5263 ev
= samba_tevent_context_init(talloc_tos());
5265 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
5269 req
= oplock5_send(ev
, ev
, cli
, fname
, pipe_down
[1]);
5271 d_fprintf(stderr
, "oplock5_send failed\n");
5275 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
5278 "tevent_req_poll_ntstatus failed: %s\n",
5283 status
= oplock5_recv(req
);
5285 if (!NT_STATUS_IS_OK(status
)) {
5287 "oplock5 failed: %s\n",
5295 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5298 Test delete on close semantics.
5300 static bool run_deletetest(int dummy
)
5302 struct cli_state
*cli1
= NULL
;
5303 struct cli_state
*cli2
= NULL
;
5304 const char *fname
= "\\delete.file";
5305 uint16_t fnum1
= (uint16_t)-1;
5306 uint16_t fnum2
= (uint16_t)-1;
5307 bool correct
= false;
5310 printf("starting delete test\n");
5312 if (!torture_open_connection(&cli1
, 0)) {
5316 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
5318 /* Test 1 - this should delete the file on close. */
5320 cli_setatr(cli1
, fname
, 0, 0);
5321 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5323 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
5324 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
5325 FILE_DELETE_ON_CLOSE
, 0, &fnum1
, NULL
);
5326 if (!NT_STATUS_IS_OK(status
)) {
5327 printf("[1] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5331 status
= cli_close(cli1
, fnum1
);
5332 if (!NT_STATUS_IS_OK(status
)) {
5333 printf("[1] close failed (%s)\n", nt_errstr(status
));
5337 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
5338 if (NT_STATUS_IS_OK(status
)) {
5339 printf("[1] open of %s succeeded (should fail)\n", fname
);
5343 printf("first delete on close test succeeded.\n");
5345 /* Test 2 - this should delete the file on close. */
5347 cli_setatr(cli1
, fname
, 0, 0);
5348 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5350 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
,
5351 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
5352 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5353 if (!NT_STATUS_IS_OK(status
)) {
5354 printf("[2] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5358 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5359 if (!NT_STATUS_IS_OK(status
)) {
5360 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status
));
5364 status
= cli_close(cli1
, fnum1
);
5365 if (!NT_STATUS_IS_OK(status
)) {
5366 printf("[2] close failed (%s)\n", nt_errstr(status
));
5370 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5371 if (NT_STATUS_IS_OK(status
)) {
5372 printf("[2] open of %s succeeded should have been deleted on close !\n", fname
);
5373 status
= cli_close(cli1
, fnum1
);
5374 if (!NT_STATUS_IS_OK(status
)) {
5375 printf("[2] close failed (%s)\n", nt_errstr(status
));
5377 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5381 printf("second delete on close test succeeded.\n");
5384 cli_setatr(cli1
, fname
, 0, 0);
5385 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5387 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
,
5388 FILE_ATTRIBUTE_NORMAL
,
5389 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5390 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5391 if (!NT_STATUS_IS_OK(status
)) {
5392 printf("[3] open - 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
5396 /* This should fail with a sharing violation - open for delete is only compatible
5397 with SHARE_DELETE. */
5399 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5400 FILE_ATTRIBUTE_NORMAL
,
5401 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5402 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5403 if (NT_STATUS_IS_OK(status
)) {
5404 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname
);
5408 /* This should succeed. */
5409 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5410 FILE_ATTRIBUTE_NORMAL
,
5411 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5412 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5413 if (!NT_STATUS_IS_OK(status
)) {
5414 printf("[3] open - 3 of %s failed (%s)\n", fname
, nt_errstr(status
));
5418 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5419 if (!NT_STATUS_IS_OK(status
)) {
5420 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status
));
5424 status
= cli_close(cli1
, fnum1
);
5425 if (!NT_STATUS_IS_OK(status
)) {
5426 printf("[3] close 1 failed (%s)\n", nt_errstr(status
));
5430 status
= cli_close(cli1
, fnum2
);
5431 if (!NT_STATUS_IS_OK(status
)) {
5432 printf("[3] close 2 failed (%s)\n", nt_errstr(status
));
5436 /* This should fail - file should no longer be there. */
5438 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5439 if (NT_STATUS_IS_OK(status
)) {
5440 printf("[3] open of %s succeeded should have been deleted on close !\n", fname
);
5441 status
= cli_close(cli1
, fnum1
);
5442 if (!NT_STATUS_IS_OK(status
)) {
5443 printf("[3] close failed (%s)\n", nt_errstr(status
));
5445 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5449 printf("third delete on close test succeeded.\n");
5452 cli_setatr(cli1
, fname
, 0, 0);
5453 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5455 status
= cli_ntcreate(cli1
, fname
, 0,
5456 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5457 FILE_ATTRIBUTE_NORMAL
,
5458 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5459 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5460 if (!NT_STATUS_IS_OK(status
)) {
5461 printf("[4] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5465 /* This should succeed. */
5466 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5467 FILE_ATTRIBUTE_NORMAL
,
5468 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5469 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5470 if (!NT_STATUS_IS_OK(status
)) {
5471 printf("[4] open - 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
5475 status
= cli_close(cli1
, fnum2
);
5476 if (!NT_STATUS_IS_OK(status
)) {
5477 printf("[4] close - 1 failed (%s)\n", nt_errstr(status
));
5481 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5482 if (!NT_STATUS_IS_OK(status
)) {
5483 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status
));
5487 /* This should fail - no more opens once delete on close set. */
5488 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5489 FILE_ATTRIBUTE_NORMAL
,
5490 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5491 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5492 if (NT_STATUS_IS_OK(status
)) {
5493 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname
);
5497 status
= cli_close(cli1
, fnum1
);
5498 if (!NT_STATUS_IS_OK(status
)) {
5499 printf("[4] close - 2 failed (%s)\n", nt_errstr(status
));
5503 printf("fourth delete on close test succeeded.\n");
5506 cli_setatr(cli1
, fname
, 0, 0);
5507 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5509 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
, &fnum1
);
5510 if (!NT_STATUS_IS_OK(status
)) {
5511 printf("[5] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5515 /* This should fail - only allowed on NT opens with DELETE access. */
5517 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5518 if (NT_STATUS_IS_OK(status
)) {
5519 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5523 status
= cli_close(cli1
, fnum1
);
5524 if (!NT_STATUS_IS_OK(status
)) {
5525 printf("[5] close failed (%s)\n", nt_errstr(status
));
5529 printf("fifth delete on close test succeeded.\n");
5532 cli_setatr(cli1
, fname
, 0, 0);
5533 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5535 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
|FILE_WRITE_DATA
,
5536 FILE_ATTRIBUTE_NORMAL
,
5537 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5538 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5539 if (!NT_STATUS_IS_OK(status
)) {
5540 printf("[6] open of %s failed (%s)\n", fname
,
5545 /* This should fail - only allowed on NT opens with DELETE access. */
5547 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5548 if (NT_STATUS_IS_OK(status
)) {
5549 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5553 status
= cli_close(cli1
, fnum1
);
5554 if (!NT_STATUS_IS_OK(status
)) {
5555 printf("[6] close failed (%s)\n", nt_errstr(status
));
5559 printf("sixth delete on close test succeeded.\n");
5562 cli_setatr(cli1
, fname
, 0, 0);
5563 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5565 status
= cli_ntcreate(cli1
, fname
, 0,
5566 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5567 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
5568 0, 0, &fnum1
, NULL
);
5569 if (!NT_STATUS_IS_OK(status
)) {
5570 printf("[7] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5574 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5575 if (!NT_STATUS_IS_OK(status
)) {
5576 printf("[7] setting delete_on_close on file failed !\n");
5580 status
= cli_nt_delete_on_close(cli1
, fnum1
, false);
5581 if (!NT_STATUS_IS_OK(status
)) {
5582 printf("[7] unsetting delete_on_close on file failed !\n");
5586 status
= cli_close(cli1
, fnum1
);
5587 if (!NT_STATUS_IS_OK(status
)) {
5588 printf("[7] close - 1 failed (%s)\n", nt_errstr(status
));
5592 /* This next open should succeed - we reset the flag. */
5593 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5594 if (!NT_STATUS_IS_OK(status
)) {
5595 printf("[7] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5599 status
= cli_close(cli1
, fnum1
);
5600 if (!NT_STATUS_IS_OK(status
)) {
5601 printf("[7] close - 2 failed (%s)\n", nt_errstr(status
));
5605 printf("seventh 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 if (!torture_open_connection(&cli2
, 1)) {
5612 printf("[8] failed to open second connection.\n");
5616 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
5618 status
= cli_ntcreate(cli1
, fname
, 0,
5619 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5620 FILE_ATTRIBUTE_NORMAL
,
5621 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5622 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5623 if (!NT_STATUS_IS_OK(status
)) {
5624 printf("[8] open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
5628 status
= cli_ntcreate(cli2
, fname
, 0,
5629 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5630 FILE_ATTRIBUTE_NORMAL
,
5631 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5632 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5633 if (!NT_STATUS_IS_OK(status
)) {
5634 printf("[8] open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
5638 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5639 if (!NT_STATUS_IS_OK(status
)) {
5640 printf("[8] setting delete_on_close on file failed !\n");
5644 status
= cli_close(cli1
, fnum1
);
5645 if (!NT_STATUS_IS_OK(status
)) {
5646 printf("[8] close - 1 failed (%s)\n", nt_errstr(status
));
5650 status
= cli_close(cli2
, fnum2
);
5651 if (!NT_STATUS_IS_OK(status
)) {
5652 printf("[8] close - 2 failed (%s)\n", nt_errstr(status
));
5656 /* This should fail.. */
5657 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5658 if (NT_STATUS_IS_OK(status
)) {
5659 printf("[8] open of %s succeeded should have been deleted on close !\n", fname
);
5663 printf("eighth delete on close test succeeded.\n");
5667 /* This should fail - we need to set DELETE_ACCESS. */
5668 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
|FILE_WRITE_DATA
,
5669 FILE_ATTRIBUTE_NORMAL
,
5672 FILE_DELETE_ON_CLOSE
, 0, &fnum1
, NULL
);
5673 if (NT_STATUS_IS_OK(status
)) {
5674 printf("[9] open of %s succeeded should have failed!\n", fname
);
5678 printf("ninth delete on close test succeeded.\n");
5682 status
= cli_ntcreate(cli1
, fname
, 0,
5683 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5684 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
5685 FILE_OVERWRITE_IF
, FILE_DELETE_ON_CLOSE
,
5687 if (!NT_STATUS_IS_OK(status
)) {
5688 printf("[10] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5692 /* This should delete the file. */
5693 status
= cli_close(cli1
, fnum1
);
5694 if (!NT_STATUS_IS_OK(status
)) {
5695 printf("[10] close failed (%s)\n", nt_errstr(status
));
5699 /* This should fail.. */
5700 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5701 if (NT_STATUS_IS_OK(status
)) {
5702 printf("[10] open of %s succeeded should have been deleted on close !\n", fname
);
5706 printf("tenth 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 /* Can we open a read-only file with delete access? */
5715 /* Create a readonly file. */
5716 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
|FILE_WRITE_DATA
,
5717 FILE_ATTRIBUTE_READONLY
, FILE_SHARE_NONE
,
5718 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5719 if (!NT_STATUS_IS_OK(status
)) {
5720 printf("[11] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5724 status
= cli_close(cli1
, fnum1
);
5725 if (!NT_STATUS_IS_OK(status
)) {
5726 printf("[11] close failed (%s)\n", nt_errstr(status
));
5730 /* Now try open for delete access. */
5731 status
= cli_ntcreate(cli1
, fname
, 0,
5732 FILE_READ_ATTRIBUTES
|DELETE_ACCESS
,
5734 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5735 FILE_OPEN
, 0, 0, &fnum1
, NULL
);
5736 if (!NT_STATUS_IS_OK(status
)) {
5737 printf("[11] open of %s failed: %s\n", fname
, nt_errstr(status
));
5741 cli_close(cli1
, fnum1
);
5743 printf("eleventh delete on close test succeeded.\n");
5747 * like test 4 but with initial delete on close
5750 cli_setatr(cli1
, fname
, 0, 0);
5751 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5753 status
= cli_ntcreate(cli1
, fname
, 0,
5754 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5755 FILE_ATTRIBUTE_NORMAL
,
5756 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5758 FILE_DELETE_ON_CLOSE
, 0, &fnum1
, NULL
);
5759 if (!NT_STATUS_IS_OK(status
)) {
5760 printf("[12] open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
5764 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5765 FILE_ATTRIBUTE_NORMAL
,
5766 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5767 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5768 if (!NT_STATUS_IS_OK(status
)) {
5769 printf("[12] open 2 of %s failed(%s).\n", fname
, nt_errstr(status
));
5773 status
= cli_close(cli1
, fnum2
);
5774 if (!NT_STATUS_IS_OK(status
)) {
5775 printf("[12] close 1 failed (%s)\n", nt_errstr(status
));
5779 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5780 if (!NT_STATUS_IS_OK(status
)) {
5781 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status
));
5785 /* This should fail - no more opens once delete on close set. */
5786 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5787 FILE_ATTRIBUTE_NORMAL
,
5788 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5789 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5790 if (NT_STATUS_IS_OK(status
)) {
5791 printf("[12] open 3 of %s succeeded - should fail).\n", fname
);
5795 status
= cli_nt_delete_on_close(cli1
, fnum1
, false);
5796 if (!NT_STATUS_IS_OK(status
)) {
5797 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status
));
5801 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5802 FILE_ATTRIBUTE_NORMAL
,
5803 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5804 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5805 if (!NT_STATUS_IS_OK(status
)) {
5806 printf("[12] open 4 of %s failed (%s)\n", fname
, nt_errstr(status
));
5810 status
= cli_close(cli1
, fnum2
);
5811 if (!NT_STATUS_IS_OK(status
)) {
5812 printf("[12] close 2 failed (%s)\n", nt_errstr(status
));
5816 status
= cli_close(cli1
, fnum1
);
5817 if (!NT_STATUS_IS_OK(status
)) {
5818 printf("[12] close 3 failed (%s)\n", nt_errstr(status
));
5823 * setting delete on close on the handle does
5824 * not unset the initial delete on close...
5826 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5827 FILE_ATTRIBUTE_NORMAL
,
5828 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5829 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5830 if (NT_STATUS_IS_OK(status
)) {
5831 printf("[12] open 5 of %s succeeded - should fail).\n", fname
);
5833 } else if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
5834 printf("ntcreate returned %s, expected "
5835 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5840 printf("twelfth delete on close test succeeded.\n");
5843 printf("finished delete test\n");
5848 /* FIXME: This will crash if we aborted before cli2 got
5849 * intialized, because these functions don't handle
5850 * uninitialized connections. */
5852 if (fnum1
!= (uint16_t)-1) cli_close(cli1
, fnum1
);
5853 if (fnum2
!= (uint16_t)-1) cli_close(cli1
, fnum2
);
5854 cli_setatr(cli1
, fname
, 0, 0);
5855 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5857 if (cli1
&& !torture_close_connection(cli1
)) {
5860 if (cli2
&& !torture_close_connection(cli2
)) {
5866 struct delete_stream_state
{
5870 static void delete_stream_unlinked(struct tevent_req
*subreq
);
5871 static void delete_stream_closed(struct tevent_req
*subreq
);
5873 static struct tevent_req
*delete_stream_send(
5874 TALLOC_CTX
*mem_ctx
,
5875 struct tevent_context
*ev
,
5876 struct cli_state
*cli
,
5877 const char *base_fname
,
5878 uint16_t stream_fnum
)
5880 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5881 struct delete_stream_state
*state
= NULL
;
5883 req
= tevent_req_create(
5884 mem_ctx
, &state
, struct delete_stream_state
);
5889 subreq
= cli_unlink_send(
5894 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5895 if (tevent_req_nomem(subreq
, req
)) {
5896 return tevent_req_post(req
, ev
);
5898 tevent_req_set_callback(subreq
, delete_stream_unlinked
, req
);
5900 subreq
= cli_close_send(state
, ev
, cli
, stream_fnum
);
5901 if (tevent_req_nomem(subreq
, req
)) {
5902 return tevent_req_post(req
, ev
);
5904 tevent_req_set_callback(subreq
, delete_stream_closed
, req
);
5909 static void delete_stream_unlinked(struct tevent_req
*subreq
)
5911 struct tevent_req
*req
= tevent_req_callback_data(
5912 subreq
, struct tevent_req
);
5913 struct delete_stream_state
*state
= tevent_req_data(
5914 req
, struct delete_stream_state
);
5917 status
= cli_unlink_recv(subreq
);
5918 TALLOC_FREE(subreq
);
5919 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
5920 printf("cli_unlink returned %s\n",
5922 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
5925 if (!state
->closed
) {
5926 /* close reply should have come in first */
5927 printf("Not closed\n");
5928 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
5931 tevent_req_done(req
);
5934 static void delete_stream_closed(struct tevent_req
*subreq
)
5936 struct tevent_req
*req
= tevent_req_callback_data(
5937 subreq
, struct tevent_req
);
5938 struct delete_stream_state
*state
= tevent_req_data(
5939 req
, struct delete_stream_state
);
5942 status
= cli_close_recv(subreq
);
5943 TALLOC_FREE(subreq
);
5944 if (tevent_req_nterror(req
, status
)) {
5947 /* also waiting for the unlink to come back */
5948 state
->closed
= true;
5951 static NTSTATUS
delete_stream_recv(struct tevent_req
*req
)
5953 return tevent_req_simple_recv_ntstatus(req
);
5956 static bool run_delete_stream(int dummy
)
5958 struct tevent_context
*ev
= NULL
;
5959 struct tevent_req
*req
= NULL
;
5960 struct cli_state
*cli
= NULL
;
5961 const char fname
[] = "delete_stream";
5962 const char fname_stream
[] = "delete_stream:Zone.Identifier:$DATA";
5963 uint16_t fnum1
, fnum2
;
5967 printf("Starting stream delete test\n");
5969 ok
= torture_open_connection(&cli
, 0);
5974 cli_setatr(cli
, fname
, 0, 0);
5975 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5977 /* Create the file. */
5978 status
= cli_ntcreate(
5982 READ_CONTROL_ACCESS
,
5984 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5990 if (!NT_STATUS_IS_OK(status
)) {
5992 "cli_ntcreate of %s failed (%s)\n",
5997 status
= cli_close(cli
, fnum1
);
5998 if (!NT_STATUS_IS_OK(status
)) {
6000 "cli_close of %s failed (%s)\n",
6006 /* Now create the stream. */
6007 status
= cli_ntcreate(
6013 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6020 if (!NT_STATUS_IS_OK(status
)) {
6022 "cli_ntcreate of %s failed (%s)\n",
6028 /* open it a second time */
6030 status
= cli_ntcreate(
6036 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6043 if (!NT_STATUS_IS_OK(status
)) {
6045 "2nd cli_ntcreate of %s failed (%s)\n",
6051 ev
= samba_tevent_context_init(talloc_tos());
6053 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
6057 req
= delete_stream_send(ev
, ev
, cli
, fname
, fnum1
);
6059 d_fprintf(stderr
, "delete_stream_send failed\n");
6063 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
6066 "tevent_req_poll_ntstatus failed: %s\n",
6071 status
= delete_stream_recv(req
);
6073 if (!NT_STATUS_IS_OK(status
)) {
6075 "delete_stream failed: %s\n",
6080 status
= cli_close(cli
, fnum2
);
6081 if (!NT_STATUS_IS_OK(status
)) {
6083 "close failed: %s\n",
6088 status
= cli_unlink(
6089 cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6090 if (!NT_STATUS_IS_OK(status
)) {
6092 "unlink failed: %s\n",
6101 Exercise delete on close semantics - use on the PRINT1 share in torture
6104 static bool run_delete_print_test(int dummy
)
6106 struct cli_state
*cli1
= NULL
;
6107 const char *fname
= "print_delete.file";
6108 uint16_t fnum1
= (uint16_t)-1;
6109 bool correct
= false;
6110 const char *buf
= "print file data\n";
6113 printf("starting print delete test\n");
6115 if (!torture_open_connection(&cli1
, 0)) {
6119 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
6121 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
6122 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
6123 0, 0, &fnum1
, NULL
);
6124 if (!NT_STATUS_IS_OK(status
)) {
6125 printf("open of %s failed (%s)\n",
6131 status
= cli_writeall(cli1
,
6134 (const uint8_t *)buf
,
6136 strlen(buf
), /* size */
6138 if (!NT_STATUS_IS_OK(status
)) {
6139 printf("writing print file data failed (%s)\n",
6144 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
6145 if (!NT_STATUS_IS_OK(status
)) {
6146 printf("setting delete_on_close failed (%s)\n",
6151 status
= cli_close(cli1
, fnum1
);
6152 if (!NT_STATUS_IS_OK(status
)) {
6153 printf("close failed (%s)\n", nt_errstr(status
));
6157 printf("finished print delete test\n");
6163 if (fnum1
!= (uint16_t)-1) {
6164 cli_close(cli1
, fnum1
);
6167 if (cli1
&& !torture_close_connection(cli1
)) {
6173 static bool run_deletetest_ln(int dummy
)
6175 struct cli_state
*cli
;
6176 const char *fname
= "\\delete1";
6177 const char *fname_ln
= "\\delete1_ln";
6181 bool correct
= true;
6184 printf("starting deletetest-ln\n");
6186 if (!torture_open_connection(&cli
, 0)) {
6190 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6191 cli_unlink(cli
, fname_ln
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6193 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
6195 /* Create the file. */
6196 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
6197 if (!NT_STATUS_IS_OK(status
)) {
6198 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
6202 status
= cli_close(cli
, fnum
);
6203 if (!NT_STATUS_IS_OK(status
)) {
6204 printf("close1 failed (%s)\n", nt_errstr(status
));
6208 /* Now create a hardlink. */
6209 status
= cli_hardlink(cli
, fname
, fname_ln
);
6210 if (!NT_STATUS_IS_OK(status
)) {
6211 printf("nt hardlink failed (%s)\n", nt_errstr(status
));
6215 /* Open the original file. */
6216 status
= cli_ntcreate(cli
, fname
, 0, FILE_READ_DATA
,
6217 FILE_ATTRIBUTE_NORMAL
,
6218 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6219 FILE_OPEN_IF
, 0, 0, &fnum
, NULL
);
6220 if (!NT_STATUS_IS_OK(status
)) {
6221 printf("ntcreate of %s failed (%s)\n", fname
, nt_errstr(status
));
6225 /* Unlink the hard link path. */
6226 status
= cli_ntcreate(cli
, fname_ln
, 0, DELETE_ACCESS
,
6227 FILE_ATTRIBUTE_NORMAL
,
6228 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6229 FILE_OPEN_IF
, 0, 0, &fnum1
, NULL
);
6230 if (!NT_STATUS_IS_OK(status
)) {
6231 printf("ntcreate of %s failed (%s)\n", fname_ln
, nt_errstr(status
));
6234 status
= cli_nt_delete_on_close(cli
, fnum1
, true);
6235 if (!NT_STATUS_IS_OK(status
)) {
6236 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6237 __location__
, fname_ln
, nt_errstr(status
));
6241 status
= cli_close(cli
, fnum1
);
6242 if (!NT_STATUS_IS_OK(status
)) {
6243 printf("close %s failed (%s)\n",
6244 fname_ln
, nt_errstr(status
));
6248 status
= cli_close(cli
, fnum
);
6249 if (!NT_STATUS_IS_OK(status
)) {
6250 printf("close %s failed (%s)\n",
6251 fname
, nt_errstr(status
));
6255 /* Ensure the original file is still there. */
6256 status
= cli_getatr(cli
, fname
, NULL
, NULL
, &t
);
6257 if (!NT_STATUS_IS_OK(status
)) {
6258 printf("%s getatr on file %s failed (%s)\n",
6265 /* Ensure the link path is gone. */
6266 status
= cli_getatr(cli
, fname_ln
, NULL
, NULL
, &t
);
6267 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
6268 printf("%s, getatr for file %s returned wrong error code %s "
6269 "- should have been deleted\n",
6271 fname_ln
, nt_errstr(status
));
6275 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6276 cli_unlink(cli
, fname_ln
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6278 if (!torture_close_connection(cli
)) {
6282 printf("finished deletetest-ln\n");
6288 print out server properties
6290 static bool run_properties(int dummy
)
6292 struct cli_state
*cli
;
6293 bool correct
= True
;
6295 printf("starting properties test\n");
6299 if (!torture_open_connection(&cli
, 0)) {
6303 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
6305 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli
->conn
));
6307 if (!torture_close_connection(cli
)) {
6316 /* FIRST_DESIRED_ACCESS 0xf019f */
6317 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6318 FILE_READ_EA| /* 0xf */ \
6319 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6320 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6321 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6322 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6323 /* SECOND_DESIRED_ACCESS 0xe0080 */
6324 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6325 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6326 WRITE_OWNER_ACCESS /* 0xe0000 */
6329 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6330 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6332 WRITE_OWNER_ACCESS /* */
6336 Test ntcreate calls made by xcopy
6338 static bool run_xcopy(int dummy
)
6340 static struct cli_state
*cli1
;
6341 const char *fname
= "\\test.txt";
6342 bool correct
= True
;
6343 uint16_t fnum1
, fnum2
;
6346 printf("starting xcopy test\n");
6348 if (!torture_open_connection(&cli1
, 0)) {
6352 status
= cli_ntcreate(cli1
, fname
, 0, FIRST_DESIRED_ACCESS
,
6353 FILE_ATTRIBUTE_ARCHIVE
, FILE_SHARE_NONE
,
6354 FILE_OVERWRITE_IF
, 0x4044, 0, &fnum1
, NULL
);
6355 if (!NT_STATUS_IS_OK(status
)) {
6356 printf("First open failed - %s\n", nt_errstr(status
));
6360 status
= cli_ntcreate(cli1
, fname
, 0, SECOND_DESIRED_ACCESS
, 0,
6361 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6362 FILE_OPEN
, 0x200000, 0, &fnum2
, NULL
);
6363 if (!NT_STATUS_IS_OK(status
)) {
6364 printf("second open failed - %s\n", nt_errstr(status
));
6368 if (!torture_close_connection(cli1
)) {
6376 Test rename on files open with share delete and no share delete.
6378 static bool run_rename(int dummy
)
6380 static struct cli_state
*cli1
;
6381 const char *fname
= "\\test.txt";
6382 const char *fname1
= "\\test1.txt";
6383 bool correct
= True
;
6388 printf("starting rename test\n");
6390 if (!torture_open_connection(&cli1
, 0)) {
6394 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6395 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6397 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
6398 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_READ
,
6399 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6400 if (!NT_STATUS_IS_OK(status
)) {
6401 printf("First open failed - %s\n", nt_errstr(status
));
6405 status
= cli_rename(cli1
, fname
, fname1
, false);
6406 if (!NT_STATUS_IS_OK(status
)) {
6407 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status
));
6409 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6413 status
= cli_close(cli1
, fnum1
);
6414 if (!NT_STATUS_IS_OK(status
)) {
6415 printf("close - 1 failed (%s)\n", nt_errstr(status
));
6419 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6420 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6421 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
, FILE_ATTRIBUTE_NORMAL
,
6423 FILE_SHARE_DELETE
|FILE_SHARE_NONE
,
6425 FILE_SHARE_DELETE
|FILE_SHARE_READ
,
6427 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6428 if (!NT_STATUS_IS_OK(status
)) {
6429 printf("Second open failed - %s\n", nt_errstr(status
));
6433 status
= cli_rename(cli1
, fname
, fname1
, false);
6434 if (!NT_STATUS_IS_OK(status
)) {
6435 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status
));
6438 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6441 status
= cli_close(cli1
, fnum1
);
6442 if (!NT_STATUS_IS_OK(status
)) {
6443 printf("close - 2 failed (%s)\n", nt_errstr(status
));
6447 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6448 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6450 status
= cli_ntcreate(cli1
, fname
, 0, READ_CONTROL_ACCESS
,
6451 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
6452 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6453 if (!NT_STATUS_IS_OK(status
)) {
6454 printf("Third open failed - %s\n", nt_errstr(status
));
6459 status
= cli_rename(cli1
, fname
, fname1
, false);
6460 if (!NT_STATUS_IS_OK(status
)) {
6461 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status
));
6464 printf("Third rename succeeded (SHARE_NONE)\n");
6467 status
= cli_close(cli1
, fnum1
);
6468 if (!NT_STATUS_IS_OK(status
)) {
6469 printf("close - 3 failed (%s)\n", nt_errstr(status
));
6473 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6474 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6478 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
6479 FILE_ATTRIBUTE_NORMAL
,
6480 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
6481 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6482 if (!NT_STATUS_IS_OK(status
)) {
6483 printf("Fourth open failed - %s\n", nt_errstr(status
));
6487 status
= cli_rename(cli1
, fname
, fname1
, false);
6488 if (!NT_STATUS_IS_OK(status
)) {
6489 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status
));
6491 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6495 status
= cli_close(cli1
, fnum1
);
6496 if (!NT_STATUS_IS_OK(status
)) {
6497 printf("close - 4 failed (%s)\n", nt_errstr(status
));
6501 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6502 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6506 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
6507 FILE_ATTRIBUTE_NORMAL
,
6508 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
6509 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6510 if (!NT_STATUS_IS_OK(status
)) {
6511 printf("Fifth open failed - %s\n", nt_errstr(status
));
6515 status
= cli_rename(cli1
, fname
, fname1
, false);
6516 if (!NT_STATUS_IS_OK(status
)) {
6517 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status
));
6520 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status
));
6524 status
= cli_close(cli1
, fnum1
);
6525 if (!NT_STATUS_IS_OK(status
)) {
6526 printf("close - 5 failed (%s)\n", nt_errstr(status
));
6530 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6531 status
= cli_getatr(cli1
, fname1
, &attr
, NULL
, NULL
);
6532 if (!NT_STATUS_IS_OK(status
)) {
6533 printf("getatr on file %s failed - %s ! \n",
6534 fname1
, nt_errstr(status
));
6537 if (attr
!= FILE_ATTRIBUTE_ARCHIVE
) {
6538 printf("Renamed file %s has wrong attr 0x%x "
6539 "(should be 0x%x)\n",
6542 (unsigned int)FILE_ATTRIBUTE_ARCHIVE
);
6545 printf("Renamed file %s has archive bit set\n", fname1
);
6549 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6550 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6552 if (!torture_close_connection(cli1
)) {
6560 Test rename into a directory with an ACL denying it.
6562 static bool run_rename_access(int dummy
)
6564 static struct cli_state
*cli
= NULL
;
6565 static struct cli_state
*posix_cli
= NULL
;
6566 const char *src
= "test.txt";
6567 const char *dname
= "dir";
6568 const char *dst
= "dir\\test.txt";
6569 const char *dsrc
= "test.dir";
6570 const char *ddst
= "dir\\test.dir";
6571 uint16_t fnum
= (uint16_t)-1;
6572 struct security_descriptor
*sd
= NULL
;
6573 struct security_descriptor
*newsd
= NULL
;
6575 TALLOC_CTX
*frame
= NULL
;
6577 frame
= talloc_stackframe();
6578 printf("starting rename access test\n");
6580 /* Windows connection. */
6581 if (!torture_open_connection(&cli
, 0)) {
6585 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
6587 /* Posix connection. */
6588 if (!torture_open_connection(&posix_cli
, 0)) {
6592 smbXcli_conn_set_sockopt(posix_cli
->conn
, sockops
);
6594 status
= torture_setup_unix_extensions(posix_cli
);
6595 if (!NT_STATUS_IS_OK(status
)) {
6599 /* Start with a clean slate. */
6600 cli_unlink(cli
, src
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6601 cli_unlink(cli
, dst
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6602 cli_rmdir(cli
, dsrc
);
6603 cli_rmdir(cli
, ddst
);
6604 cli_rmdir(cli
, dname
);
6607 * Setup the destination directory with a DENY ACE to
6608 * prevent new files within it.
6610 status
= cli_ntcreate(cli
,
6613 FILE_READ_ATTRIBUTES
|READ_CONTROL_ACCESS
|
6614 WRITE_DAC_ACCESS
|FILE_READ_DATA
|
6616 FILE_ATTRIBUTE_DIRECTORY
,
6617 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6619 FILE_DIRECTORY_FILE
,
6623 if (!NT_STATUS_IS_OK(status
)) {
6624 printf("Create of %s - %s\n", dname
, nt_errstr(status
));
6628 status
= cli_query_secdesc(cli
,
6632 if (!NT_STATUS_IS_OK(status
)) {
6633 printf("cli_query_secdesc failed for %s (%s)\n",
6634 dname
, nt_errstr(status
));
6638 newsd
= security_descriptor_dacl_create(frame
,
6643 SEC_ACE_TYPE_ACCESS_DENIED
,
6644 SEC_DIR_ADD_FILE
|SEC_DIR_ADD_SUBDIR
,
6647 if (newsd
== NULL
) {
6650 sd
->dacl
= security_acl_concatenate(frame
,
6653 if (sd
->dacl
== NULL
) {
6656 status
= cli_set_secdesc(cli
, fnum
, sd
);
6657 if (!NT_STATUS_IS_OK(status
)) {
6658 printf("cli_set_secdesc failed for %s (%s)\n",
6659 dname
, nt_errstr(status
));
6662 status
= cli_close(cli
, fnum
);
6663 if (!NT_STATUS_IS_OK(status
)) {
6664 printf("close failed for %s (%s)\n",
6665 dname
, nt_errstr(status
));
6668 /* Now go around the back and chmod to 777 via POSIX. */
6669 status
= cli_posix_chmod(posix_cli
, dname
, 0777);
6670 if (!NT_STATUS_IS_OK(status
)) {
6671 printf("cli_posix_chmod failed for %s (%s)\n",
6672 dname
, nt_errstr(status
));
6676 /* Check we can't create a file within dname via Windows. */
6677 status
= cli_openx(cli
, dst
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
6678 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6679 cli_close(posix_cli
, fnum
);
6680 printf("Create of %s should be ACCESS denied, was %s\n",
6681 dst
, nt_errstr(status
));
6685 /* Make the sample file/directory. */
6686 status
= cli_openx(cli
, src
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
6687 if (!NT_STATUS_IS_OK(status
)) {
6688 printf("open of %s failed (%s)\n", src
, nt_errstr(status
));
6691 status
= cli_close(cli
, fnum
);
6692 if (!NT_STATUS_IS_OK(status
)) {
6693 printf("cli_close failed (%s)\n", nt_errstr(status
));
6697 status
= cli_mkdir(cli
, dsrc
);
6698 if (!NT_STATUS_IS_OK(status
)) {
6699 printf("cli_mkdir of %s failed (%s)\n",
6700 dsrc
, nt_errstr(status
));
6705 * OK - renames of the new file and directory into the
6706 * dst directory should fail.
6709 status
= cli_rename(cli
, src
, dst
, false);
6710 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6711 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6712 src
, dst
, nt_errstr(status
));
6715 status
= cli_rename(cli
, dsrc
, ddst
, false);
6716 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6717 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6718 src
, dst
, nt_errstr(status
));
6728 torture_close_connection(posix_cli
);
6732 if (fnum
!= (uint16_t)-1) {
6733 cli_close(cli
, fnum
);
6735 cli_unlink(cli
, src
,
6736 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6737 cli_unlink(cli
, dst
,
6738 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6739 cli_rmdir(cli
, dsrc
);
6740 cli_rmdir(cli
, ddst
);
6741 cli_rmdir(cli
, dname
);
6743 torture_close_connection(cli
);
6751 Test owner rights ACE.
6753 static bool run_owner_rights(int dummy
)
6755 static struct cli_state
*cli
= NULL
;
6756 const char *fname
= "owner_rights.txt";
6757 uint16_t fnum
= (uint16_t)-1;
6758 struct security_descriptor
*sd
= NULL
;
6759 struct security_descriptor
*newsd
= NULL
;
6761 TALLOC_CTX
*frame
= NULL
;
6763 frame
= talloc_stackframe();
6764 printf("starting owner rights test\n");
6766 /* Windows connection. */
6767 if (!torture_open_connection(&cli
, 0)) {
6771 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
6773 /* Start with a clean slate. */
6774 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6776 /* Create the test file. */
6777 /* Now try and open for read and write-dac. */
6778 status
= cli_ntcreate(cli
,
6782 FILE_ATTRIBUTE_NORMAL
,
6783 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
6790 if (!NT_STATUS_IS_OK(status
)) {
6791 printf("Create of %s - %s\n", fname
, nt_errstr(status
));
6795 /* Get the original SD. */
6796 status
= cli_query_secdesc(cli
,
6800 if (!NT_STATUS_IS_OK(status
)) {
6801 printf("cli_query_secdesc failed for %s (%s)\n",
6802 fname
, nt_errstr(status
));
6807 * Add an "owner-rights" ACE denying WRITE_DATA,
6808 * and an "owner-rights" ACE allowing READ_DATA.
6811 newsd
= security_descriptor_dacl_create(frame
,
6816 SEC_ACE_TYPE_ACCESS_DENIED
,
6820 SEC_ACE_TYPE_ACCESS_ALLOWED
,
6824 if (newsd
== NULL
) {
6827 sd
->dacl
= security_acl_concatenate(frame
,
6830 if (sd
->dacl
== NULL
) {
6833 status
= cli_set_secdesc(cli
, fnum
, sd
);
6834 if (!NT_STATUS_IS_OK(status
)) {
6835 printf("cli_set_secdesc failed for %s (%s)\n",
6836 fname
, nt_errstr(status
));
6839 status
= cli_close(cli
, fnum
);
6840 if (!NT_STATUS_IS_OK(status
)) {
6841 printf("close failed for %s (%s)\n",
6842 fname
, nt_errstr(status
));
6845 fnum
= (uint16_t)-1;
6847 /* Try and open for FILE_WRITE_DATA */
6848 status
= cli_ntcreate(cli
,
6852 FILE_ATTRIBUTE_NORMAL
,
6853 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
6860 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6861 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
6865 /* Now try and open for FILE_READ_DATA */
6866 status
= cli_ntcreate(cli
,
6870 FILE_ATTRIBUTE_NORMAL
,
6871 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
6878 if (!NT_STATUS_IS_OK(status
)) {
6879 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
6883 status
= cli_close(cli
, fnum
);
6884 if (!NT_STATUS_IS_OK(status
)) {
6885 printf("close failed for %s (%s)\n",
6886 fname
, nt_errstr(status
));
6890 /* Restore clean slate. */
6892 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6894 /* Create the test file. */
6895 status
= cli_ntcreate(cli
,
6899 FILE_ATTRIBUTE_NORMAL
,
6900 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
6907 if (!NT_STATUS_IS_OK(status
)) {
6908 printf("Create of %s - %s\n", fname
, nt_errstr(status
));
6912 /* Get the original SD. */
6913 status
= cli_query_secdesc(cli
,
6917 if (!NT_STATUS_IS_OK(status
)) {
6918 printf("cli_query_secdesc failed for %s (%s)\n",
6919 fname
, nt_errstr(status
));
6924 * Add an "owner-rights ACE denying WRITE_DATA,
6925 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6928 newsd
= security_descriptor_dacl_create(frame
,
6933 SEC_ACE_TYPE_ACCESS_DENIED
,
6937 SEC_ACE_TYPE_ACCESS_ALLOWED
,
6938 FILE_READ_DATA
|FILE_WRITE_DATA
,
6941 if (newsd
== NULL
) {
6944 sd
->dacl
= security_acl_concatenate(frame
,
6947 if (sd
->dacl
== NULL
) {
6950 status
= cli_set_secdesc(cli
, fnum
, sd
);
6951 if (!NT_STATUS_IS_OK(status
)) {
6952 printf("cli_set_secdesc failed for %s (%s)\n",
6953 fname
, nt_errstr(status
));
6956 status
= cli_close(cli
, fnum
);
6957 if (!NT_STATUS_IS_OK(status
)) {
6958 printf("close failed for %s (%s)\n",
6959 fname
, nt_errstr(status
));
6962 fnum
= (uint16_t)-1;
6964 /* Try and open for FILE_WRITE_DATA */
6965 status
= cli_ntcreate(cli
,
6969 FILE_ATTRIBUTE_NORMAL
,
6970 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
6977 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6978 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
6982 /* Now try and open for FILE_READ_DATA */
6983 status
= cli_ntcreate(cli
,
6987 FILE_ATTRIBUTE_NORMAL
,
6988 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
6995 if (!NT_STATUS_IS_OK(status
)) {
6996 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
7000 status
= cli_close(cli
, fnum
);
7001 if (!NT_STATUS_IS_OK(status
)) {
7002 printf("close failed for %s (%s)\n",
7003 fname
, nt_errstr(status
));
7007 /* Restore clean slate. */
7009 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7012 /* Create the test file. */
7013 status
= cli_ntcreate(cli
,
7017 FILE_ATTRIBUTE_NORMAL
,
7018 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7025 if (!NT_STATUS_IS_OK(status
)) {
7026 printf("Create of %s - %s\n", fname
, nt_errstr(status
));
7030 /* Get the original SD. */
7031 status
= cli_query_secdesc(cli
,
7035 if (!NT_STATUS_IS_OK(status
)) {
7036 printf("cli_query_secdesc failed for %s (%s)\n",
7037 fname
, nt_errstr(status
));
7042 * Add an "authenticated users" ACE allowing READ_DATA,
7043 * add an "owner-rights" denying READ_DATA,
7044 * and an "authenticated users" ACE allowing WRITE_DATA.
7047 newsd
= security_descriptor_dacl_create(frame
,
7051 SID_NT_AUTHENTICATED_USERS
,
7052 SEC_ACE_TYPE_ACCESS_ALLOWED
,
7056 SEC_ACE_TYPE_ACCESS_DENIED
,
7059 SID_NT_AUTHENTICATED_USERS
,
7060 SEC_ACE_TYPE_ACCESS_ALLOWED
,
7064 if (newsd
== NULL
) {
7065 printf("newsd == NULL\n");
7068 sd
->dacl
= security_acl_concatenate(frame
,
7071 if (sd
->dacl
== NULL
) {
7072 printf("sd->dacl == NULL\n");
7075 status
= cli_set_secdesc(cli
, fnum
, sd
);
7076 if (!NT_STATUS_IS_OK(status
)) {
7077 printf("cli_set_secdesc failed for %s (%s)\n",
7078 fname
, nt_errstr(status
));
7081 status
= cli_close(cli
, fnum
);
7082 if (!NT_STATUS_IS_OK(status
)) {
7083 printf("close failed for %s (%s)\n",
7084 fname
, nt_errstr(status
));
7087 fnum
= (uint16_t)-1;
7089 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7090 status
= cli_ntcreate(cli
,
7093 FILE_READ_DATA
|FILE_WRITE_DATA
,
7094 FILE_ATTRIBUTE_NORMAL
,
7095 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7102 if (!NT_STATUS_IS_OK(status
)) {
7103 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
7107 status
= cli_close(cli
, fnum
);
7108 if (!NT_STATUS_IS_OK(status
)) {
7109 printf("close failed for %s (%s)\n",
7110 fname
, nt_errstr(status
));
7114 cli_unlink(cli
, fname
,
7115 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7123 if (fnum
!= (uint16_t)-1) {
7124 cli_close(cli
, fnum
);
7126 cli_unlink(cli
, fname
,
7127 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7128 torture_close_connection(cli
);
7136 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7137 * Note this test only works with a user with SeSecurityPrivilege set.
7139 * NB. This is also tested in samba3.base.createx_access
7140 * but this makes it very explicit what we're looking for.
7142 static bool run_smb1_system_security(int dummy
)
7144 static struct cli_state
*cli
= NULL
;
7145 const char *fname
= "system_security.txt";
7146 uint16_t fnum
= (uint16_t)-1;
7148 TALLOC_CTX
*frame
= NULL
;
7150 frame
= talloc_stackframe();
7151 printf("starting smb1 system security test\n");
7153 /* SMB1 connection - torture_open_connection() forces this. */
7154 if (!torture_open_connection(&cli
, 0)) {
7158 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
7160 /* Start with a clean slate. */
7161 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7163 /* Create the test file. */
7164 status
= cli_ntcreate(cli
,
7168 FILE_ATTRIBUTE_NORMAL
,
7169 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7176 if (!NT_STATUS_IS_OK(status
)) {
7177 printf("Create of %s - %s\n", fname
, nt_errstr(status
));
7181 status
= cli_close(cli
, fnum
);
7183 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7185 * On SMB1 this succeeds - SMB2 it fails,
7186 * see the SMB2-SACL test.
7188 status
= cli_ntcreate(cli
,
7191 SEC_FLAG_SYSTEM_SECURITY
,
7192 FILE_ATTRIBUTE_NORMAL
,
7193 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7200 if (!NT_STATUS_IS_OK(status
)) {
7201 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
7205 status
= cli_close(cli
, fnum
);
7207 cli_unlink(cli
, fname
,
7208 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7210 torture_close_connection(cli
);
7217 if (fnum
!= (uint16_t)-1) {
7218 cli_close(cli
, fnum
);
7220 cli_unlink(cli
, fname
,
7221 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7222 torture_close_connection(cli
);
7229 static bool run_pipe_number(int dummy
)
7231 struct cli_state
*cli1
;
7232 const char *pipe_name
= "\\SPOOLSS";
7237 printf("starting pipenumber test\n");
7238 if (!torture_open_connection(&cli1
, 0)) {
7242 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
7244 status
= cli_ntcreate(cli1
, pipe_name
, 0, FILE_READ_DATA
,
7245 FILE_ATTRIBUTE_NORMAL
,
7246 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
7247 FILE_OPEN_IF
, 0, 0, &fnum
, NULL
);
7248 if (!NT_STATUS_IS_OK(status
)) {
7249 printf("Open of pipe %s failed with error (%s)\n", pipe_name
, nt_errstr(status
));
7253 printf("\r%6d", num_pipes
);
7256 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes
, pipe_name
);
7257 torture_close_connection(cli1
);
7262 Test open mode returns on read-only files.
7264 static bool run_opentest(int dummy
)
7266 static struct cli_state
*cli1
;
7267 static struct cli_state
*cli2
;
7268 const char *fname
= "\\readonly.file";
7269 uint16_t fnum1
, fnum2
;
7272 bool correct
= True
;
7276 printf("starting open test\n");
7278 if (!torture_open_connection(&cli1
, 0)) {
7282 cli_setatr(cli1
, fname
, 0, 0);
7283 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7285 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
7287 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
7288 if (!NT_STATUS_IS_OK(status
)) {
7289 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
7293 status
= cli_close(cli1
, fnum1
);
7294 if (!NT_STATUS_IS_OK(status
)) {
7295 printf("close2 failed (%s)\n", nt_errstr(status
));
7299 status
= cli_setatr(cli1
, fname
, FILE_ATTRIBUTE_READONLY
, 0);
7300 if (!NT_STATUS_IS_OK(status
)) {
7301 printf("cli_setatr failed (%s)\n", nt_errstr(status
));
7305 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_WRITE
, &fnum1
);
7306 if (!NT_STATUS_IS_OK(status
)) {
7307 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
7311 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7312 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_ALL
, &fnum2
);
7314 if (check_error(__LINE__
, status
, ERRDOS
, ERRnoaccess
,
7315 NT_STATUS_ACCESS_DENIED
)) {
7316 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7319 printf("finished open test 1\n");
7321 cli_close(cli1
, fnum1
);
7323 /* Now try not readonly and ensure ERRbadshare is returned. */
7325 cli_setatr(cli1
, fname
, 0, 0);
7327 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_WRITE
, &fnum1
);
7328 if (!NT_STATUS_IS_OK(status
)) {
7329 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
7333 /* This will fail - but the error should be ERRshare. */
7334 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_ALL
, &fnum2
);
7336 if (check_error(__LINE__
, status
, ERRDOS
, ERRbadshare
,
7337 NT_STATUS_SHARING_VIOLATION
)) {
7338 printf("correct error code ERRDOS/ERRbadshare returned\n");
7341 status
= cli_close(cli1
, fnum1
);
7342 if (!NT_STATUS_IS_OK(status
)) {
7343 printf("close2 failed (%s)\n", nt_errstr(status
));
7347 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7349 printf("finished open test 2\n");
7351 /* Test truncate open disposition on file opened for read. */
7352 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
7353 if (!NT_STATUS_IS_OK(status
)) {
7354 printf("(3) open (1) of %s failed (%s)\n", fname
, nt_errstr(status
));
7358 /* write 20 bytes. */
7360 memset(buf
, '\0', 20);
7362 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, 20, NULL
);
7363 if (!NT_STATUS_IS_OK(status
)) {
7364 printf("write failed (%s)\n", nt_errstr(status
));
7368 status
= cli_close(cli1
, fnum1
);
7369 if (!NT_STATUS_IS_OK(status
)) {
7370 printf("(3) close1 failed (%s)\n", nt_errstr(status
));
7374 /* Ensure size == 20. */
7375 status
= cli_getatr(cli1
, fname
, NULL
, &fsize
, NULL
);
7376 if (!NT_STATUS_IS_OK(status
)) {
7377 printf("(3) getatr failed (%s)\n", nt_errstr(status
));
7382 printf("(3) file size != 20\n");
7386 /* Now test if we can truncate a file opened for readonly. */
7387 status
= cli_openx(cli1
, fname
, O_RDONLY
|O_TRUNC
, DENY_NONE
, &fnum1
);
7388 if (!NT_STATUS_IS_OK(status
)) {
7389 printf("(3) open (2) of %s failed (%s)\n", fname
, nt_errstr(status
));
7393 status
= cli_close(cli1
, fnum1
);
7394 if (!NT_STATUS_IS_OK(status
)) {
7395 printf("close2 failed (%s)\n", nt_errstr(status
));
7399 /* Ensure size == 0. */
7400 status
= cli_getatr(cli1
, fname
, NULL
, &fsize
, NULL
);
7401 if (!NT_STATUS_IS_OK(status
)) {
7402 printf("(3) getatr failed (%s)\n", nt_errstr(status
));
7407 printf("(3) file size != 0\n");
7410 printf("finished open test 3\n");
7412 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7414 printf("Do ctemp tests\n");
7415 status
= cli_ctemp(cli1
, talloc_tos(), "\\", &fnum1
, &tmp_path
);
7416 if (!NT_STATUS_IS_OK(status
)) {
7417 printf("ctemp failed (%s)\n", nt_errstr(status
));
7421 printf("ctemp gave path %s\n", tmp_path
);
7422 status
= cli_close(cli1
, fnum1
);
7423 if (!NT_STATUS_IS_OK(status
)) {
7424 printf("close of temp failed (%s)\n", nt_errstr(status
));
7427 status
= cli_unlink(cli1
, tmp_path
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7428 if (!NT_STATUS_IS_OK(status
)) {
7429 printf("unlink of temp failed (%s)\n", nt_errstr(status
));
7432 /* Test the non-io opens... */
7434 if (!torture_open_connection(&cli2
, 1)) {
7438 cli_setatr(cli2
, fname
, 0, 0);
7439 cli_unlink(cli2
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7441 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
7443 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7444 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_ATTRIBUTES
,
7445 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7446 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7447 if (!NT_STATUS_IS_OK(status
)) {
7448 printf("TEST #1 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7452 status
= cli_ntcreate(cli2
, fname
, 0, FILE_READ_ATTRIBUTES
,
7453 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7454 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7455 if (!NT_STATUS_IS_OK(status
)) {
7456 printf("TEST #1 open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7460 status
= cli_close(cli1
, fnum1
);
7461 if (!NT_STATUS_IS_OK(status
)) {
7462 printf("TEST #1 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7466 status
= cli_close(cli2
, fnum2
);
7467 if (!NT_STATUS_IS_OK(status
)) {
7468 printf("TEST #1 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7472 printf("non-io open test #1 passed.\n");
7474 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7476 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7478 status
= cli_ntcreate(cli1
, fname
, 0,
7479 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7480 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7481 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7482 if (!NT_STATUS_IS_OK(status
)) {
7483 printf("TEST #2 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7487 status
= cli_ntcreate(cli2
, fname
, 0, FILE_READ_ATTRIBUTES
,
7488 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7489 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7490 if (!NT_STATUS_IS_OK(status
)) {
7491 printf("TEST #2 open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7495 status
= cli_close(cli1
, fnum1
);
7496 if (!NT_STATUS_IS_OK(status
)) {
7497 printf("TEST #2 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7501 status
= cli_close(cli2
, fnum2
);
7502 if (!NT_STATUS_IS_OK(status
)) {
7503 printf("TEST #2 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7507 printf("non-io open test #2 passed.\n");
7509 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7511 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7513 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_ATTRIBUTES
,
7514 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7515 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7516 if (!NT_STATUS_IS_OK(status
)) {
7517 printf("TEST #3 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7521 status
= cli_ntcreate(cli2
, fname
, 0,
7522 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7523 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7524 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7525 if (!NT_STATUS_IS_OK(status
)) {
7526 printf("TEST #3 open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7530 status
= cli_close(cli1
, fnum1
);
7531 if (!NT_STATUS_IS_OK(status
)) {
7532 printf("TEST #3 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7536 status
= cli_close(cli2
, fnum2
);
7537 if (!NT_STATUS_IS_OK(status
)) {
7538 printf("TEST #3 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7542 printf("non-io open test #3 passed.\n");
7544 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7546 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7548 status
= cli_ntcreate(cli1
, fname
, 0,
7549 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7550 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7551 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7552 if (!NT_STATUS_IS_OK(status
)) {
7553 printf("TEST #4 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7557 status
= cli_ntcreate(cli2
, fname
, 0,
7558 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7559 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7560 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7561 if (NT_STATUS_IS_OK(status
)) {
7562 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname
, nt_errstr(status
));
7566 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname
, nt_errstr(status
), "sharing violation");
7568 status
= cli_close(cli1
, fnum1
);
7569 if (!NT_STATUS_IS_OK(status
)) {
7570 printf("TEST #4 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7574 printf("non-io open test #4 passed.\n");
7576 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7578 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7580 status
= cli_ntcreate(cli1
, fname
, 0,
7581 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7582 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_DELETE
,
7583 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7584 if (!NT_STATUS_IS_OK(status
)) {
7585 printf("TEST #5 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7589 status
= cli_ntcreate(cli2
, fname
, 0,
7590 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7591 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_DELETE
,
7592 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7593 if (!NT_STATUS_IS_OK(status
)) {
7594 printf("TEST #5 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 #5 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 #5 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7610 printf("non-io open test #5 passed.\n");
7612 printf("TEST #6 testing 1 non-io open, one io open\n");
7614 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7616 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
,
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 #6 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7624 status
= cli_ntcreate(cli2
, fname
, 0, FILE_READ_ATTRIBUTES
,
7625 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_READ
,
7626 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7627 if (!NT_STATUS_IS_OK(status
)) {
7628 printf("TEST #6 open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7632 status
= cli_close(cli1
, fnum1
);
7633 if (!NT_STATUS_IS_OK(status
)) {
7634 printf("TEST #6 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7638 status
= cli_close(cli2
, fnum2
);
7639 if (!NT_STATUS_IS_OK(status
)) {
7640 printf("TEST #6 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7644 printf("non-io open test #6 passed.\n");
7646 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7648 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7650 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
,
7651 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7652 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7653 if (!NT_STATUS_IS_OK(status
)) {
7654 printf("TEST #7 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7658 status
= cli_ntcreate(cli2
, fname
, 0,
7659 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7660 FILE_ATTRIBUTE_NORMAL
,
7661 FILE_SHARE_READ
|FILE_SHARE_DELETE
,
7662 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7663 if (NT_STATUS_IS_OK(status
)) {
7664 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname
, nt_errstr(status
));
7668 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname
, nt_errstr(status
), "sharing violation");
7670 status
= cli_close(cli1
, fnum1
);
7671 if (!NT_STATUS_IS_OK(status
)) {
7672 printf("TEST #7 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7676 printf("non-io open test #7 passed.\n");
7678 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7680 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7681 status
= cli_ntcreate(cli1
, fname
, 0, FILE_WRITE_DATA
, FILE_ATTRIBUTE_NORMAL
,
7682 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
7683 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7684 if (!NT_STATUS_IS_OK(status
)) {
7685 printf("TEST #8 open of %s failed (%s)\n", fname
, nt_errstr(status
));
7690 /* Write to ensure we have to update the file time. */
7691 status
= cli_writeall(cli1
, fnum1
, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7693 if (!NT_STATUS_IS_OK(status
)) {
7694 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status
));
7699 status
= cli_close(cli1
, fnum1
);
7700 if (!NT_STATUS_IS_OK(status
)) {
7701 printf("TEST #8 close of %s failed (%s)\n", fname
, nt_errstr(status
));
7707 if (!torture_close_connection(cli1
)) {
7710 if (!torture_close_connection(cli2
)) {
7717 NTSTATUS
torture_setup_unix_extensions(struct cli_state
*cli
)
7719 uint16_t major
, minor
;
7720 uint32_t caplow
, caphigh
;
7723 if (!SERVER_HAS_UNIX_CIFS(cli
)) {
7724 printf("Server doesn't support UNIX CIFS extensions.\n");
7725 return NT_STATUS_NOT_SUPPORTED
;
7728 status
= cli_unix_extensions_version(cli
, &major
, &minor
, &caplow
,
7730 if (!NT_STATUS_IS_OK(status
)) {
7731 printf("Server didn't return UNIX CIFS extensions: %s\n",
7736 status
= cli_set_unix_extensions_capabilities(cli
, major
, minor
,
7738 if (!NT_STATUS_IS_OK(status
)) {
7739 printf("Server doesn't support setting UNIX CIFS extensions: "
7740 "%s.\n", nt_errstr(status
));
7744 return NT_STATUS_OK
;
7748 Test POSIX open /mkdir calls.
7750 static bool run_simple_posix_open_test(int dummy
)
7752 static struct cli_state
*cli1
;
7753 const char *fname
= "posix:file";
7754 const char *hname
= "posix:hlink";
7755 const char *sname
= "posix:symlink";
7756 const char *dname
= "posix:dir";
7758 char *target
= NULL
;
7759 uint16_t fnum1
= (uint16_t)-1;
7760 SMB_STRUCT_STAT sbuf
;
7761 bool correct
= false;
7764 const char *fname_windows
= "windows_file";
7765 uint16_t fnum2
= (uint16_t)-1;
7768 printf("Starting simple POSIX open test\n");
7770 if (!torture_open_connection(&cli1
, 0)) {
7774 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
7776 status
= torture_setup_unix_extensions(cli1
);
7777 if (!NT_STATUS_IS_OK(status
)) {
7781 cli_setatr(cli1
, fname
, 0, 0);
7782 cli_posix_unlink(cli1
, fname
);
7783 cli_setatr(cli1
, dname
, 0, 0);
7784 cli_posix_rmdir(cli1
, dname
);
7785 cli_setatr(cli1
, hname
, 0, 0);
7786 cli_posix_unlink(cli1
, hname
);
7787 cli_setatr(cli1
, sname
, 0, 0);
7788 cli_posix_unlink(cli1
, sname
);
7789 cli_setatr(cli1
, fname_windows
, 0, 0);
7790 cli_posix_unlink(cli1
, fname_windows
);
7792 /* Create a directory. */
7793 status
= cli_posix_mkdir(cli1
, dname
, 0777);
7794 if (!NT_STATUS_IS_OK(status
)) {
7795 printf("POSIX mkdir of %s failed (%s)\n", dname
, nt_errstr(status
));
7799 status
= cli_posix_open(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
,
7801 if (!NT_STATUS_IS_OK(status
)) {
7802 printf("POSIX create of %s failed (%s)\n", fname
, nt_errstr(status
));
7806 /* Test ftruncate - set file size. */
7807 status
= cli_ftruncate(cli1
, fnum1
, 1000);
7808 if (!NT_STATUS_IS_OK(status
)) {
7809 printf("ftruncate failed (%s)\n", nt_errstr(status
));
7813 /* Ensure st_size == 1000 */
7814 status
= cli_posix_stat(cli1
, fname
, &sbuf
);
7815 if (!NT_STATUS_IS_OK(status
)) {
7816 printf("stat failed (%s)\n", nt_errstr(status
));
7820 if (sbuf
.st_ex_size
!= 1000) {
7821 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf
.st_ex_size
);
7825 /* Ensure st_mode == 0600 */
7826 if ((sbuf
.st_ex_mode
& 07777) != 0600) {
7827 printf("posix_open - bad permissions 0%o != 0600\n",
7828 (unsigned int)(sbuf
.st_ex_mode
& 07777));
7832 /* Test ftruncate - set file size back to zero. */
7833 status
= cli_ftruncate(cli1
, fnum1
, 0);
7834 if (!NT_STATUS_IS_OK(status
)) {
7835 printf("ftruncate failed (%s)\n", nt_errstr(status
));
7839 status
= cli_close(cli1
, fnum1
);
7840 if (!NT_STATUS_IS_OK(status
)) {
7841 printf("close failed (%s)\n", nt_errstr(status
));
7845 /* Now open the file again for read only. */
7846 status
= cli_posix_open(cli1
, fname
, O_RDONLY
, 0, &fnum1
);
7847 if (!NT_STATUS_IS_OK(status
)) {
7848 printf("POSIX open of %s failed (%s)\n", fname
, nt_errstr(status
));
7852 /* Now unlink while open. */
7853 status
= cli_posix_unlink(cli1
, fname
);
7854 if (!NT_STATUS_IS_OK(status
)) {
7855 printf("POSIX unlink of %s failed (%s)\n", fname
, nt_errstr(status
));
7859 status
= cli_close(cli1
, fnum1
);
7860 if (!NT_STATUS_IS_OK(status
)) {
7861 printf("close(2) failed (%s)\n", nt_errstr(status
));
7865 /* Ensure the file has gone. */
7866 status
= cli_posix_open(cli1
, fname
, O_RDONLY
, 0, &fnum1
);
7867 if (NT_STATUS_IS_OK(status
)) {
7868 printf("POSIX open of %s succeeded, should have been deleted.\n", fname
);
7872 /* Create again to test open with O_TRUNC. */
7873 status
= cli_posix_open(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, 0600, &fnum1
);
7874 if (!NT_STATUS_IS_OK(status
)) {
7875 printf("POSIX create of %s failed (%s)\n", fname
, nt_errstr(status
));
7879 /* Test ftruncate - set file size. */
7880 status
= cli_ftruncate(cli1
, fnum1
, 1000);
7881 if (!NT_STATUS_IS_OK(status
)) {
7882 printf("ftruncate failed (%s)\n", nt_errstr(status
));
7886 /* Ensure st_size == 1000 */
7887 status
= cli_posix_stat(cli1
, fname
, &sbuf
);
7888 if (!NT_STATUS_IS_OK(status
)) {
7889 printf("stat failed (%s)\n", nt_errstr(status
));
7893 if (sbuf
.st_ex_size
!= 1000) {
7894 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf
.st_ex_size
);
7898 status
= cli_close(cli1
, fnum1
);
7899 if (!NT_STATUS_IS_OK(status
)) {
7900 printf("close(2) failed (%s)\n", nt_errstr(status
));
7904 /* Re-open with O_TRUNC. */
7905 status
= cli_posix_open(cli1
, fname
, O_WRONLY
|O_TRUNC
, 0600, &fnum1
);
7906 if (!NT_STATUS_IS_OK(status
)) {
7907 printf("POSIX create of %s failed (%s)\n", fname
, nt_errstr(status
));
7911 /* Ensure st_size == 0 */
7912 status
= cli_posix_stat(cli1
, fname
, &sbuf
);
7913 if (!NT_STATUS_IS_OK(status
)) {
7914 printf("stat failed (%s)\n", nt_errstr(status
));
7918 if (sbuf
.st_ex_size
!= 0) {
7919 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf
.st_ex_size
);
7923 status
= cli_close(cli1
, fnum1
);
7924 if (!NT_STATUS_IS_OK(status
)) {
7925 printf("close failed (%s)\n", nt_errstr(status
));
7929 status
= cli_posix_unlink(cli1
, fname
);
7930 if (!NT_STATUS_IS_OK(status
)) {
7931 printf("POSIX unlink of %s failed (%s)\n", fname
, nt_errstr(status
));
7935 status
= cli_posix_open(cli1
, dname
, O_RDONLY
, 0, &fnum1
);
7936 if (!NT_STATUS_IS_OK(status
)) {
7937 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7938 dname
, nt_errstr(status
));
7942 cli_close(cli1
, fnum1
);
7944 /* What happens when we try and POSIX open a directory for write ? */
7945 status
= cli_posix_open(cli1
, dname
, O_RDWR
, 0, &fnum1
);
7946 if (NT_STATUS_IS_OK(status
)) {
7947 printf("POSIX open of directory %s succeeded, "
7948 "should have failed.\n",
7952 if (!check_both_error(__LINE__
, status
, ERRDOS
, EISDIR
,
7953 NT_STATUS_FILE_IS_A_DIRECTORY
)) {
7958 /* Create the file. */
7959 status
= cli_posix_open(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
,
7961 if (!NT_STATUS_IS_OK(status
)) {
7962 printf("POSIX create of %s failed (%s)\n", fname
, nt_errstr(status
));
7966 /* Write some data into it. */
7967 status
= cli_writeall(cli1
, fnum1
, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7969 if (!NT_STATUS_IS_OK(status
)) {
7970 printf("cli_write failed: %s\n", nt_errstr(status
));
7974 cli_close(cli1
, fnum1
);
7976 /* Now create a hardlink. */
7977 status
= cli_posix_hardlink(cli1
, fname
, hname
);
7978 if (!NT_STATUS_IS_OK(status
)) {
7979 printf("POSIX hardlink of %s failed (%s)\n", hname
, nt_errstr(status
));
7983 /* Now create a symlink. */
7984 status
= cli_posix_symlink(cli1
, fname
, sname
);
7985 if (!NT_STATUS_IS_OK(status
)) {
7986 printf("POSIX symlink of %s failed (%s)\n", sname
, nt_errstr(status
));
7990 /* Open the hardlink for read. */
7991 status
= cli_posix_open(cli1
, hname
, O_RDONLY
, 0, &fnum1
);
7992 if (!NT_STATUS_IS_OK(status
)) {
7993 printf("POSIX open of %s failed (%s)\n", hname
, nt_errstr(status
));
7997 status
= cli_read(cli1
, fnum1
, buf
, 0, 10, &nread
);
7998 if (!NT_STATUS_IS_OK(status
)) {
7999 printf("POSIX read of %s failed (%s)\n", hname
,
8002 } else if (nread
!= 10) {
8003 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8004 hname
, (unsigned long)nread
, 10);
8008 if (memcmp(buf
, "TEST DATA\n", 10)) {
8009 printf("invalid data read from hardlink\n");
8013 /* Do a POSIX lock/unlock. */
8014 status
= cli_posix_lock(cli1
, fnum1
, 0, 100, true, READ_LOCK
);
8015 if (!NT_STATUS_IS_OK(status
)) {
8016 printf("POSIX lock failed %s\n", nt_errstr(status
));
8020 /* Punch a hole in the locked area. */
8021 status
= cli_posix_unlock(cli1
, fnum1
, 10, 80);
8022 if (!NT_STATUS_IS_OK(status
)) {
8023 printf("POSIX unlock failed %s\n", nt_errstr(status
));
8027 cli_close(cli1
, fnum1
);
8029 /* Open the symlink for read - this should fail. A POSIX
8030 client should not be doing opens on a symlink. */
8031 status
= cli_posix_open(cli1
, sname
, O_RDONLY
, 0, &fnum1
);
8032 if (NT_STATUS_IS_OK(status
)) {
8033 printf("POSIX open of %s succeeded (should have failed)\n", sname
);
8036 ok
= check_both_error(
8037 __LINE__
, status
, ERRDOS
, ERRbadpath
,
8038 NT_STATUS_OBJECT_NAME_NOT_FOUND
);
8040 printf("POSIX open of %s should have failed "
8041 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8042 "failed with %s instead.\n",
8043 sname
, nt_errstr(status
));
8047 status
= cli_readlink(cli1
, sname
, talloc_tos(), &target
, NULL
, NULL
);
8048 if (!NT_STATUS_IS_OK(status
)) {
8049 printf("POSIX readlink on %s failed (%s)\n", sname
, nt_errstr(status
));
8053 if (strcmp(target
, fname
) != 0) {
8054 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8055 sname
, fname
, target
);
8059 status
= cli_posix_rmdir(cli1
, dname
);
8060 if (!NT_STATUS_IS_OK(status
)) {
8061 printf("POSIX rmdir failed (%s)\n", nt_errstr(status
));
8065 /* Check directory opens with a specific permission. */
8066 status
= cli_posix_mkdir(cli1
, dname
, 0700);
8067 if (!NT_STATUS_IS_OK(status
)) {
8068 printf("POSIX mkdir of %s failed (%s)\n", dname
, nt_errstr(status
));
8072 /* Ensure st_mode == 0700 */
8073 status
= cli_posix_stat(cli1
, dname
, &sbuf
);
8074 if (!NT_STATUS_IS_OK(status
)) {
8075 printf("stat failed (%s)\n", nt_errstr(status
));
8079 if ((sbuf
.st_ex_mode
& 07777) != 0700) {
8080 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8081 (unsigned int)(sbuf
.st_ex_mode
& 07777));
8086 * Now create a Windows file, and attempt a POSIX unlink.
8087 * This should fail with a sharing violation but due to:
8089 * [Bug 9571] Unlink after open causes smbd to panic
8091 * ensure we've fixed the lock ordering violation.
8094 status
= cli_ntcreate(cli1
, fname_windows
, 0,
8095 FILE_READ_DATA
|FILE_WRITE_DATA
, 0,
8096 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8098 0x0, 0x0, &fnum2
, NULL
);
8099 if (!NT_STATUS_IS_OK(status
)) {
8100 printf("Windows create of %s failed (%s)\n", fname_windows
,
8105 /* Now try posix_unlink. */
8106 status
= cli_posix_unlink(cli1
, fname_windows
);
8107 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
8108 printf("POSIX unlink of %s should fail "
8109 "with NT_STATUS_SHARING_VIOLATION "
8110 "got %s instead !\n",
8116 cli_close(cli1
, fnum2
);
8118 printf("Simple POSIX open test passed\n");
8123 if (fnum1
!= (uint16_t)-1) {
8124 cli_close(cli1
, fnum1
);
8125 fnum1
= (uint16_t)-1;
8128 if (fnum2
!= (uint16_t)-1) {
8129 cli_close(cli1
, fnum2
);
8130 fnum2
= (uint16_t)-1;
8133 cli_setatr(cli1
, sname
, 0, 0);
8134 cli_posix_unlink(cli1
, sname
);
8135 cli_setatr(cli1
, hname
, 0, 0);
8136 cli_posix_unlink(cli1
, hname
);
8137 cli_setatr(cli1
, fname
, 0, 0);
8138 cli_posix_unlink(cli1
, fname
);
8139 cli_setatr(cli1
, dname
, 0, 0);
8140 cli_posix_rmdir(cli1
, dname
);
8141 cli_setatr(cli1
, fname_windows
, 0, 0);
8142 cli_posix_unlink(cli1
, fname_windows
);
8144 if (!torture_close_connection(cli1
)) {
8152 Test POSIX and Windows ACLs are rejected on symlinks.
8154 static bool run_acl_symlink_test(int dummy
)
8156 static struct cli_state
*cli
;
8157 const char *fname
= "posix_file";
8158 const char *sname
= "posix_symlink";
8159 uint16_t fnum
= (uint16_t)-1;
8160 bool correct
= false;
8162 char *posix_acl
= NULL
;
8163 size_t posix_acl_len
= 0;
8164 char *posix_acl_sym
= NULL
;
8165 size_t posix_acl_len_sym
= 0;
8166 struct security_descriptor
*sd
= NULL
;
8167 TALLOC_CTX
*frame
= NULL
;
8169 frame
= talloc_stackframe();
8171 printf("Starting acl symlink test\n");
8173 if (!torture_open_connection(&cli
, 0)) {
8178 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
8180 status
= torture_setup_unix_extensions(cli
);
8181 if (!NT_STATUS_IS_OK(status
)) {
8186 cli_setatr(cli
, fname
, 0, 0);
8187 cli_posix_unlink(cli
, fname
);
8188 cli_setatr(cli
, sname
, 0, 0);
8189 cli_posix_unlink(cli
, sname
);
8191 status
= cli_ntcreate(cli
,
8194 READ_CONTROL_ACCESS
,
8196 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8203 if (!NT_STATUS_IS_OK(status
)) {
8204 printf("cli_ntcreate of %s failed (%s)\n",
8210 /* Get the Windows ACL on the file. */
8211 status
= cli_query_secdesc(cli
,
8215 if (!NT_STATUS_IS_OK(status
)) {
8216 printf("cli_query_secdesc failed (%s)\n",
8221 /* Get the POSIX ACL on the file. */
8222 status
= cli_posix_getacl(cli
,
8228 if (!NT_STATUS_IS_OK(status
)) {
8229 printf("cli_posix_getacl failed (%s)\n",
8234 status
= cli_close(cli
, fnum
);
8235 if (!NT_STATUS_IS_OK(status
)) {
8236 printf("close failed (%s)\n", nt_errstr(status
));
8239 fnum
= (uint16_t)-1;
8241 /* Now create a symlink. */
8242 status
= cli_posix_symlink(cli
, fname
, sname
);
8243 if (!NT_STATUS_IS_OK(status
)) {
8244 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8251 /* Open a handle on the symlink for SD set/get should fail. */
8252 status
= cli_ntcreate(cli
,
8255 READ_CONTROL_ACCESS
|SEC_STD_WRITE_DAC
,
8257 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8264 if (NT_STATUS_IS_OK(status
)) {
8265 printf("Symlink open for getsd/setsd of %s "
8266 "succeeded (should fail)\n",
8271 /* Try a stat-open on the symlink, should also fail. */
8272 status
= cli_ntcreate(cli
,
8275 FILE_READ_ATTRIBUTES
|FILE_WRITE_ATTRIBUTES
,
8277 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8284 if (NT_STATUS_IS_OK(status
)) {
8285 printf("Stat-open of symlink succeeded (should fail)\n");
8289 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8290 status
= cli_posix_getacl(cli
,
8296 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
8297 printf("cli_posix_getacl on a symlink gave %s. "
8298 "Should be NT_STATUS_ACCESS_DENIED.\n",
8303 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8304 status
= cli_posix_setacl(cli
,
8309 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
8310 printf("cli_posix_setacl on a symlink gave %s. "
8311 "Should be NT_STATUS_ACCESS_DENIED.\n",
8316 printf("ACL symlink test passed\n");
8321 if (fnum
!= (uint16_t)-1) {
8322 cli_close(cli
, fnum
);
8323 fnum
= (uint16_t)-1;
8326 cli_setatr(cli
, sname
, 0, 0);
8327 cli_posix_unlink(cli
, sname
);
8328 cli_setatr(cli
, fname
, 0, 0);
8329 cli_posix_unlink(cli
, fname
);
8331 if (!torture_close_connection(cli
)) {
8340 Test POSIX can delete a file containing streams.
8342 static bool run_posix_stream_delete(int dummy
)
8344 struct cli_state
*cli1
= NULL
;
8345 struct cli_state
*cli2
= NULL
;
8346 const char *fname
= "streamfile";
8347 const char *stream_fname
= "streamfile:Zone.Identifier:$DATA";
8348 uint16_t fnum1
= (uint16_t)-1;
8349 bool correct
= false;
8351 TALLOC_CTX
*frame
= NULL
;
8353 frame
= talloc_stackframe();
8355 printf("Starting POSIX stream delete test\n");
8357 if (!torture_open_connection(&cli1
, 0) ||
8358 !torture_open_connection(&cli2
, 1)) {
8363 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
8364 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
8366 status
= torture_setup_unix_extensions(cli2
);
8367 if (!NT_STATUS_IS_OK(status
)) {
8371 cli_setatr(cli1
, fname
, 0, 0);
8372 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
8374 /* Create the file. */
8375 status
= cli_ntcreate(cli1
,
8378 READ_CONTROL_ACCESS
,
8380 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8387 if (!NT_STATUS_IS_OK(status
)) {
8388 printf("cli_ntcreate of %s failed (%s)\n",
8394 status
= cli_close(cli1
, fnum1
);
8395 if (!NT_STATUS_IS_OK(status
)) {
8396 printf("cli_close of %s failed (%s)\n",
8401 fnum1
= (uint16_t)-1;
8403 /* Now create the stream. */
8404 status
= cli_ntcreate(cli1
,
8409 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
8416 if (!NT_STATUS_IS_OK(status
)) {
8417 printf("cli_ntcreate of %s failed (%s)\n",
8423 /* Leave the stream handle open... */
8425 /* POSIX unlink should fail. */
8426 status
= cli_posix_unlink(cli2
, fname
);
8427 if (NT_STATUS_IS_OK(status
)) {
8428 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8433 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
8434 printf("cli_posix_unlink of %s failed with (%s) "
8435 "should have been NT_STATUS_SHARING_VIOLATION\n",
8441 /* Close the stream handle. */
8442 status
= cli_close(cli1
, fnum1
);
8443 if (!NT_STATUS_IS_OK(status
)) {
8444 printf("cli_close of %s failed (%s)\n",
8449 fnum1
= (uint16_t)-1;
8451 /* POSIX unlink after stream handle closed should succeed. */
8452 status
= cli_posix_unlink(cli2
, fname
);
8453 if (!NT_STATUS_IS_OK(status
)) {
8454 printf("cli_posix_unlink of %s failed (%s)\n",
8460 printf("POSIX stream delete test passed\n");
8465 if (fnum1
!= (uint16_t)-1) {
8466 cli_close(cli1
, fnum1
);
8467 fnum1
= (uint16_t)-1;
8470 cli_setatr(cli1
, fname
, 0, 0);
8471 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
8473 if (!torture_close_connection(cli1
)) {
8476 if (!torture_close_connection(cli2
)) {
8485 Test setting EA's are rejected on symlinks.
8487 static bool run_ea_symlink_test(int dummy
)
8489 static struct cli_state
*cli
;
8490 const char *fname
= "posix_file_ea";
8491 const char *sname
= "posix_symlink_ea";
8492 const char *ea_name
= "testea_name";
8493 const char *ea_value
= "testea_value";
8494 uint16_t fnum
= (uint16_t)-1;
8495 bool correct
= false;
8498 struct ea_struct
*eas
= NULL
;
8499 TALLOC_CTX
*frame
= NULL
;
8501 frame
= talloc_stackframe();
8503 printf("Starting EA symlink test\n");
8505 if (!torture_open_connection(&cli
, 0)) {
8510 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
8512 status
= torture_setup_unix_extensions(cli
);
8513 if (!NT_STATUS_IS_OK(status
)) {
8518 cli_setatr(cli
, fname
, 0, 0);
8519 cli_posix_unlink(cli
, fname
);
8520 cli_setatr(cli
, sname
, 0, 0);
8521 cli_posix_unlink(cli
, sname
);
8523 status
= cli_ntcreate(cli
,
8526 READ_CONTROL_ACCESS
,
8528 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8535 if (!NT_STATUS_IS_OK(status
)) {
8536 printf("cli_ntcreate of %s failed (%s)\n",
8542 status
= cli_close(cli
, fnum
);
8543 if (!NT_STATUS_IS_OK(status
)) {
8544 printf("close failed (%s)\n",
8548 fnum
= (uint16_t)-1;
8550 /* Set an EA on the path. */
8551 status
= cli_set_ea_path(cli
,
8555 strlen(ea_value
)+1);
8557 if (!NT_STATUS_IS_OK(status
)) {
8558 printf("cli_set_ea_path failed (%s)\n",
8563 /* Now create a symlink. */
8564 status
= cli_posix_symlink(cli
, fname
, sname
);
8565 if (!NT_STATUS_IS_OK(status
)) {
8566 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8573 /* Get the EA list on the path. Should return value set. */
8574 status
= cli_get_ea_list_path(cli
,
8580 if (!NT_STATUS_IS_OK(status
)) {
8581 printf("cli_get_ea_list_path failed (%s)\n",
8586 /* Ensure the EA we set is there. */
8587 for (i
=0; i
<num_eas
; i
++) {
8588 if (strcmp(eas
[i
].name
, ea_name
) == 0 &&
8589 eas
[i
].value
.length
== strlen(ea_value
)+1 &&
8590 memcmp(eas
[i
].value
.data
,
8592 eas
[i
].value
.length
) == 0) {
8598 printf("Didn't find EA on pathname %s\n",
8606 /* Get the EA list on the symlink. Should return empty list. */
8607 status
= cli_get_ea_list_path(cli
,
8613 if (!NT_STATUS_IS_OK(status
)) {
8614 printf("cli_get_ea_list_path failed (%s)\n",
8620 printf("cli_get_ea_list_path failed (%s)\n",
8625 /* Set an EA on the symlink. Should fail. */
8626 status
= cli_set_ea_path(cli
,
8630 strlen(ea_value
)+1);
8632 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
8633 printf("cli_set_ea_path on a symlink gave %s. "
8634 "Should be NT_STATUS_ACCESS_DENIED.\n",
8639 printf("EA symlink test passed\n");
8644 if (fnum
!= (uint16_t)-1) {
8645 cli_close(cli
, fnum
);
8646 fnum
= (uint16_t)-1;
8649 cli_setatr(cli
, sname
, 0, 0);
8650 cli_posix_unlink(cli
, sname
);
8651 cli_setatr(cli
, fname
, 0, 0);
8652 cli_posix_unlink(cli
, fname
);
8654 if (!torture_close_connection(cli
)) {
8663 Test POSIX locks are OFD-locks.
8665 static bool run_posix_ofd_lock_test(int dummy
)
8667 static struct cli_state
*cli
;
8668 const char *fname
= "posix_file";
8669 uint16_t fnum1
= (uint16_t)-1;
8670 uint16_t fnum2
= (uint16_t)-1;
8671 bool correct
= false;
8673 TALLOC_CTX
*frame
= NULL
;
8675 frame
= talloc_stackframe();
8677 printf("Starting POSIX ofd-lock test\n");
8679 if (!torture_open_connection(&cli
, 0)) {
8684 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
8686 status
= torture_setup_unix_extensions(cli
);
8687 if (!NT_STATUS_IS_OK(status
)) {
8692 cli_setatr(cli
, fname
, 0, 0);
8693 cli_posix_unlink(cli
, fname
);
8695 /* Open the file twice. */
8696 status
= cli_posix_open(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
,
8698 if (!NT_STATUS_IS_OK(status
)) {
8699 printf("First POSIX open of %s failed\n", fname
);
8703 status
= cli_posix_open(cli
, fname
, O_RDWR
, 0, &fnum2
);
8704 if (!NT_STATUS_IS_OK(status
)) {
8705 printf("First POSIX open of %s failed\n", fname
);
8709 /* Set a 0-50 lock on fnum1. */
8710 status
= cli_posix_lock(cli
, fnum1
, 0, 50, false, WRITE_LOCK
);
8711 if (!NT_STATUS_IS_OK(status
)) {
8712 printf("POSIX lock (1) failed %s\n", nt_errstr(status
));
8716 /* Set a 60-100 lock on fnum2. */
8717 status
= cli_posix_lock(cli
, fnum2
, 60, 100, false, WRITE_LOCK
);
8718 if (!NT_STATUS_IS_OK(status
)) {
8719 printf("POSIX lock (2) failed %s\n", nt_errstr(status
));
8723 /* close fnum1 - 0-50 lock should go away. */
8724 status
= cli_close(cli
, fnum1
);
8725 if (!NT_STATUS_IS_OK(status
)) {
8726 printf("close failed (%s)\n",
8730 fnum1
= (uint16_t)-1;
8732 /* Change the lock context. */
8733 cli_setpid(cli
, cli_getpid(cli
) + 1);
8735 /* Re-open fnum1. */
8736 status
= cli_posix_open(cli
, fname
, O_RDWR
, 0, &fnum1
);
8737 if (!NT_STATUS_IS_OK(status
)) {
8738 printf("Third POSIX open of %s failed\n", fname
);
8742 /* 60-100 lock should still be there. */
8743 status
= cli_posix_lock(cli
, fnum1
, 60, 100, false, WRITE_LOCK
);
8744 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
8745 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status
));
8749 /* 0-50 lock should be gone. */
8750 status
= cli_posix_lock(cli
, fnum1
, 0, 50, false, WRITE_LOCK
);
8751 if (!NT_STATUS_IS_OK(status
)) {
8752 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status
));
8756 printf("POSIX OFD lock test passed\n");
8761 if (fnum1
!= (uint16_t)-1) {
8762 cli_close(cli
, fnum1
);
8763 fnum1
= (uint16_t)-1;
8765 if (fnum2
!= (uint16_t)-1) {
8766 cli_close(cli
, fnum2
);
8767 fnum2
= (uint16_t)-1;
8770 cli_setatr(cli
, fname
, 0, 0);
8771 cli_posix_unlink(cli
, fname
);
8773 if (!torture_close_connection(cli
)) {
8781 struct posix_blocking_state
{
8782 struct tevent_context
*ev
;
8783 struct cli_state
*cli1
;
8785 struct cli_state
*cli2
;
8791 static void posix_blocking_locked(struct tevent_req
*subreq
);
8792 static void posix_blocking_gotblocked(struct tevent_req
*subreq
);
8793 static void posix_blocking_gotecho(struct tevent_req
*subreq
);
8794 static void posix_blocking_unlocked(struct tevent_req
*subreq
);
8796 static struct tevent_req
*posix_blocking_send(
8797 TALLOC_CTX
*mem_ctx
,
8798 struct tevent_context
*ev
,
8799 struct cli_state
*cli1
,
8801 struct cli_state
*cli2
,
8804 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
8805 struct posix_blocking_state
*state
= NULL
;
8807 req
= tevent_req_create(mem_ctx
, &state
, struct posix_blocking_state
);
8813 state
->fnum1
= fnum1
;
8815 state
->fnum2
= fnum2
;
8817 subreq
= cli_posix_lock_send(
8826 if (tevent_req_nomem(subreq
, req
)) {
8827 return tevent_req_post(req
, ev
);
8829 tevent_req_set_callback(subreq
, posix_blocking_locked
, req
);
8833 static void posix_blocking_locked(struct tevent_req
*subreq
)
8835 struct tevent_req
*req
= tevent_req_callback_data(
8836 subreq
, struct tevent_req
);
8837 struct posix_blocking_state
*state
= tevent_req_data(
8838 req
, struct posix_blocking_state
);
8841 status
= cli_posix_lock_recv(subreq
);
8842 TALLOC_FREE(subreq
);
8843 if (tevent_req_nterror(req
, status
)) {
8847 subreq
= cli_posix_lock_send(
8856 if (tevent_req_nomem(subreq
, req
)) {
8859 tevent_req_set_callback(subreq
, posix_blocking_gotblocked
, req
);
8861 /* Make sure the blocking request is delivered */
8862 subreq
= cli_echo_send(
8867 (DATA_BLOB
) { .data
= (uint8_t *)state
, .length
= 1 });
8868 if (tevent_req_nomem(subreq
, req
)) {
8871 tevent_req_set_callback(subreq
, posix_blocking_gotecho
, req
);
8874 static void posix_blocking_gotblocked(struct tevent_req
*subreq
)
8876 struct tevent_req
*req
= tevent_req_callback_data(
8877 subreq
, struct tevent_req
);
8878 struct posix_blocking_state
*state
= tevent_req_data(
8879 req
, struct posix_blocking_state
);
8882 status
= cli_posix_lock_recv(subreq
);
8883 TALLOC_FREE(subreq
);
8884 if (tevent_req_nterror(req
, status
)) {
8887 if (!state
->gotecho
) {
8888 printf("blocked req got through before echo\n");
8889 tevent_req_nterror(req
, NT_STATUS_INVALID_LOCK_SEQUENCE
);
8892 tevent_req_done(req
);
8895 static void posix_blocking_gotecho(struct tevent_req
*subreq
)
8897 struct tevent_req
*req
= tevent_req_callback_data(
8898 subreq
, struct tevent_req
);
8899 struct posix_blocking_state
*state
= tevent_req_data(
8900 req
, struct posix_blocking_state
);
8903 status
= cli_echo_recv(subreq
);
8904 TALLOC_FREE(subreq
);
8905 if (tevent_req_nterror(req
, status
)) {
8908 if (state
->gotblocked
) {
8909 printf("blocked req got through before echo\n");
8910 tevent_req_nterror(req
, NT_STATUS_INVALID_LOCK_SEQUENCE
);
8913 state
->gotecho
= true;
8915 subreq
= cli_posix_lock_send(
8924 if (tevent_req_nomem(subreq
, req
)) {
8927 tevent_req_set_callback(subreq
, posix_blocking_unlocked
, req
);
8930 static void posix_blocking_unlocked(struct tevent_req
*subreq
)
8932 struct tevent_req
*req
= tevent_req_callback_data(
8933 subreq
, struct tevent_req
);
8936 status
= cli_posix_lock_recv(subreq
);
8937 TALLOC_FREE(subreq
);
8938 if (tevent_req_nterror(req
, status
)) {
8941 /* tevent_req_done in posix_blocking_gotlocked */
8944 static NTSTATUS
posix_blocking_recv(struct tevent_req
*req
)
8946 return tevent_req_simple_recv_ntstatus(req
);
8949 static bool run_posix_blocking_lock(int dummy
)
8951 struct tevent_context
*ev
= NULL
;
8952 struct cli_state
*cli1
= NULL
, *cli2
= NULL
;
8953 const char *fname
= "posix_blocking";
8954 uint16_t fnum1
= UINT16_MAX
, fnum2
= UINT16_MAX
;
8955 struct tevent_req
*req
= NULL
;
8960 printf("Starting posix blocking lock test\n");
8962 ev
= samba_tevent_context_init(NULL
);
8967 ok
= torture_open_connection(&cli1
, 0);
8971 ok
= torture_open_connection(&cli2
, 0);
8976 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
8978 status
= torture_setup_unix_extensions(cli1
);
8979 if (!NT_STATUS_IS_OK(status
)) {
8983 status
= torture_setup_unix_extensions(cli2
);
8984 if (!NT_STATUS_IS_OK(status
)) {
8988 cli_setatr(cli1
, fname
, 0, 0);
8989 cli_posix_unlink(cli1
, fname
);
8991 status
= cli_posix_open(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
,
8993 if (!NT_STATUS_IS_OK(status
)) {
8994 printf("First POSIX open of %s failed: %s\n",
9000 status
= cli_posix_open(cli2
, fname
, O_RDWR
, 0600, &fnum2
);
9001 if (!NT_STATUS_IS_OK(status
)) {
9002 printf("Second POSIX open of %s failed: %s\n",
9008 req
= posix_blocking_send(ev
, ev
, cli1
, fnum1
, cli2
, fnum2
);
9010 printf("cli_posix_blocking failed\n");
9014 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
9016 printf("tevent_req_poll_ntstatus failed: %s\n",
9020 status
= posix_blocking_recv(req
);
9022 if (!NT_STATUS_IS_OK(status
)) {
9023 printf("posix_blocking_recv returned %s\n",
9031 if (fnum1
!= UINT16_MAX
) {
9032 cli_close(cli1
, fnum1
);
9035 if (fnum2
!= UINT16_MAX
) {
9036 cli_close(cli2
, fnum2
);
9041 cli_setatr(cli1
, fname
, 0, 0);
9042 cli_posix_unlink(cli1
, fname
);
9048 ok
&= torture_close_connection(cli1
);
9052 ok
&= torture_close_connection(cli2
);
9064 Test POSIX mkdir is case-sensitive.
9066 static bool run_posix_mkdir_test(int dummy
)
9068 static struct cli_state
*cli
;
9069 const char *fname_foo
= "POSIX_foo";
9070 const char *fname_foo_Foo
= "POSIX_foo/Foo";
9071 const char *fname_foo_foo
= "POSIX_foo/foo";
9072 const char *fname_Foo
= "POSIX_Foo";
9073 const char *fname_Foo_Foo
= "POSIX_Foo/Foo";
9074 const char *fname_Foo_foo
= "POSIX_Foo/foo";
9075 bool correct
= false;
9077 TALLOC_CTX
*frame
= NULL
;
9078 uint16_t fnum
= (uint16_t)-1;
9080 frame
= talloc_stackframe();
9082 printf("Starting POSIX mkdir test\n");
9084 if (!torture_open_connection(&cli
, 0)) {
9089 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
9091 status
= torture_setup_unix_extensions(cli
);
9092 if (!NT_STATUS_IS_OK(status
)) {
9097 cli_posix_rmdir(cli
, fname_foo_foo
);
9098 cli_posix_rmdir(cli
, fname_foo_Foo
);
9099 cli_posix_rmdir(cli
, fname_foo
);
9101 cli_posix_rmdir(cli
, fname_Foo_foo
);
9102 cli_posix_rmdir(cli
, fname_Foo_Foo
);
9103 cli_posix_rmdir(cli
, fname_Foo
);
9106 * Create a file POSIX_foo then try
9107 * and use it in a directory path by
9108 * doing mkdir POSIX_foo/bar.
9109 * The mkdir should fail with
9110 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9113 status
= cli_posix_open(cli
,
9118 if (!NT_STATUS_IS_OK(status
)) {
9119 printf("cli_posix_open of %s failed error %s\n",
9125 status
= cli_posix_mkdir(cli
, fname_foo_foo
, 0777);
9126 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9127 printf("cli_posix_mkdir of %s should fail with "
9128 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9135 status
= cli_close(cli
, fnum
);
9136 if (!NT_STATUS_IS_OK(status
)) {
9137 printf("cli_close failed %s\n", nt_errstr(status
));
9140 fnum
= (uint16_t)-1;
9142 status
= cli_posix_unlink(cli
, fname_foo
);
9143 if (!NT_STATUS_IS_OK(status
)) {
9144 printf("cli_posix_unlink of %s failed error %s\n",
9151 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9152 * posix_open, posix_unlink, on
9153 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9154 * not silently create POSIX_foo/foo.
9157 status
= cli_posix_mkdir(cli
, fname_foo_foo
, 0777);
9158 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9159 printf("cli_posix_mkdir of %s should fail with "
9160 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9167 status
= cli_posix_rmdir(cli
, fname_foo_foo
);
9168 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9169 printf("cli_posix_rmdir of %s should fail with "
9170 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9177 status
= cli_posix_open(cli
,
9182 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9183 printf("cli_posix_open of %s should fail with "
9184 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9191 status
= cli_posix_unlink(cli
, fname_foo_foo
);
9192 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9193 printf("cli_posix_unlink of %s should fail with "
9194 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9201 status
= cli_posix_mkdir(cli
, fname_foo
, 0777);
9202 if (!NT_STATUS_IS_OK(status
)) {
9203 printf("cli_posix_mkdir of %s failed\n", fname_foo
);
9207 status
= cli_posix_mkdir(cli
, fname_Foo
, 0777);
9208 if (!NT_STATUS_IS_OK(status
)) {
9209 printf("cli_posix_mkdir of %s failed\n", fname_Foo
);
9213 status
= cli_posix_mkdir(cli
, fname_foo_foo
, 0777);
9214 if (!NT_STATUS_IS_OK(status
)) {
9215 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo
);
9219 status
= cli_posix_mkdir(cli
, fname_foo_Foo
, 0777);
9220 if (!NT_STATUS_IS_OK(status
)) {
9221 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo
);
9225 status
= cli_posix_mkdir(cli
, fname_Foo_foo
, 0777);
9226 if (!NT_STATUS_IS_OK(status
)) {
9227 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo
);
9231 status
= cli_posix_mkdir(cli
, fname_Foo_Foo
, 0777);
9232 if (!NT_STATUS_IS_OK(status
)) {
9233 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo
);
9237 printf("POSIX mkdir test passed\n");
9242 if (fnum
!= (uint16_t)-1) {
9243 cli_close(cli
, fnum
);
9244 fnum
= (uint16_t)-1;
9247 cli_posix_rmdir(cli
, fname_foo_foo
);
9248 cli_posix_rmdir(cli
, fname_foo_Foo
);
9249 cli_posix_rmdir(cli
, fname_foo
);
9251 cli_posix_rmdir(cli
, fname_Foo_foo
);
9252 cli_posix_rmdir(cli
, fname_Foo_Foo
);
9253 cli_posix_rmdir(cli
, fname_Foo
);
9255 if (!torture_close_connection(cli
)) {
9263 struct posix_acl_oplock_state
{
9264 struct tevent_context
*ev
;
9265 struct cli_state
*cli
;
9271 static void posix_acl_oplock_got_break(struct tevent_req
*req
)
9273 struct posix_acl_oplock_state
*state
= tevent_req_callback_data(
9274 req
, struct posix_acl_oplock_state
);
9279 status
= cli_smb_oplock_break_waiter_recv(req
, &fnum
, &level
);
9281 if (!NT_STATUS_IS_OK(status
)) {
9282 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9286 *state
->got_break
= true;
9288 req
= cli_oplock_ack_send(state
, state
->ev
, state
->cli
, fnum
,
9291 printf("cli_oplock_ack_send failed\n");
9296 static void posix_acl_oplock_got_acl(struct tevent_req
*req
)
9298 struct posix_acl_oplock_state
*state
= tevent_req_callback_data(
9299 req
, struct posix_acl_oplock_state
);
9300 size_t ret_size
= 0;
9301 char *ret_data
= NULL
;
9303 state
->status
= cli_posix_getacl_recv(req
,
9308 if (!NT_STATUS_IS_OK(state
->status
)) {
9309 printf("cli_posix_getacl_recv returned %s\n",
9310 nt_errstr(state
->status
));
9312 *state
->acl_ret
= true;
9315 static bool run_posix_acl_oplock_test(int dummy
)
9317 struct tevent_context
*ev
;
9318 struct cli_state
*cli1
, *cli2
;
9319 struct tevent_req
*oplock_req
, *getacl_req
;
9320 const char *fname
= "posix_acl_oplock";
9322 int saved_use_oplocks
= use_oplocks
;
9324 bool correct
= true;
9325 bool got_break
= false;
9326 bool acl_ret
= false;
9328 struct posix_acl_oplock_state
*state
;
9330 printf("starting posix_acl_oplock test\n");
9332 if (!torture_open_connection(&cli1
, 0)) {
9333 use_level_II_oplocks
= false;
9334 use_oplocks
= saved_use_oplocks
;
9338 if (!torture_open_connection(&cli2
, 1)) {
9339 use_level_II_oplocks
= false;
9340 use_oplocks
= saved_use_oplocks
;
9344 /* Setup posix on cli2 only. */
9345 status
= torture_setup_unix_extensions(cli2
);
9346 if (!NT_STATUS_IS_OK(status
)) {
9350 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
9351 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
9353 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9355 /* Create the file on the Windows connection. */
9356 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
9358 if (!NT_STATUS_IS_OK(status
)) {
9359 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
9363 status
= cli_close(cli1
, fnum
);
9364 if (!NT_STATUS_IS_OK(status
)) {
9365 printf("close1 failed (%s)\n", nt_errstr(status
));
9369 cli1
->use_oplocks
= true;
9371 /* Open with oplock. */
9372 status
= cli_ntcreate(cli1
,
9376 FILE_ATTRIBUTE_NORMAL
,
9377 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
9384 if (!NT_STATUS_IS_OK(status
)) {
9385 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
9389 ev
= samba_tevent_context_init(talloc_tos());
9391 printf("tevent_context_init failed\n");
9395 state
= talloc_zero(ev
, struct posix_acl_oplock_state
);
9396 if (state
== NULL
) {
9397 printf("talloc failed\n");
9402 state
->got_break
= &got_break
;
9403 state
->acl_ret
= &acl_ret
;
9405 oplock_req
= cli_smb_oplock_break_waiter_send(
9406 talloc_tos(), ev
, cli1
);
9407 if (oplock_req
== NULL
) {
9408 printf("cli_smb_oplock_break_waiter_send failed\n");
9411 tevent_req_set_callback(oplock_req
, posix_acl_oplock_got_break
, state
);
9413 /* Get ACL on POSIX connection - should break oplock. */
9414 getacl_req
= cli_posix_getacl_send(talloc_tos(),
9418 if (getacl_req
== NULL
) {
9419 printf("cli_posix_getacl_send failed\n");
9422 tevent_req_set_callback(getacl_req
, posix_acl_oplock_got_acl
, state
);
9424 while (!got_break
|| !acl_ret
) {
9426 ret
= tevent_loop_once(ev
);
9428 printf("tevent_loop_once failed: %s\n",
9434 if (!NT_STATUS_IS_OK(state
->status
)) {
9435 printf("getacl failed (%s)\n", nt_errstr(state
->status
));
9439 status
= cli_close(cli1
, fnum
);
9440 if (!NT_STATUS_IS_OK(status
)) {
9441 printf("close2 failed (%s)\n", nt_errstr(status
));
9445 status
= cli_unlink(cli1
,
9447 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9448 if (!NT_STATUS_IS_OK(status
)) {
9449 printf("unlink failed (%s)\n", nt_errstr(status
));
9453 if (!torture_close_connection(cli1
)) {
9456 if (!torture_close_connection(cli2
)) {
9464 printf("finished posix acl oplock test\n");
9469 static bool run_posix_acl_shareroot_test(int dummy
)
9471 struct cli_state
*cli
;
9473 bool correct
= false;
9474 char *posix_acl
= NULL
;
9475 size_t posix_acl_len
= 0;
9476 uint16_t num_file_acls
= 0;
9477 uint16_t num_dir_acls
= 0;
9479 uint32_t expected_size
= 0;
9480 bool got_user
= false;
9481 bool got_group
= false;
9482 bool got_other
= false;
9483 TALLOC_CTX
*frame
= NULL
;
9485 frame
= talloc_stackframe();
9487 printf("starting posix_acl_shareroot test\n");
9489 if (!torture_open_connection(&cli
, 0)) {
9494 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
9496 status
= torture_setup_unix_extensions(cli
);
9497 if (!NT_STATUS_IS_OK(status
)) {
9498 printf("Failed to setup unix extensions\n");
9502 /* Get the POSIX ACL on the root of the share. */
9503 status
= cli_posix_getacl(cli
,
9509 if (!NT_STATUS_IS_OK(status
)) {
9510 printf("cli_posix_getacl of '.' failed (%s)\n",
9515 if (posix_acl_len
< 6 ||
9516 SVAL(posix_acl
,0) != SMB_POSIX_ACL_VERSION
) {
9517 printf("getfacl ., unknown POSIX acl version %u.\n",
9518 (unsigned int)CVAL(posix_acl
,0) );
9522 num_file_acls
= SVAL(posix_acl
,2);
9523 num_dir_acls
= SVAL(posix_acl
,4);
9524 expected_size
= SMB_POSIX_ACL_HEADER_SIZE
+
9525 SMB_POSIX_ACL_ENTRY_SIZE
*
9526 (num_file_acls
+num_dir_acls
);
9528 if (posix_acl_len
!= expected_size
) {
9529 printf("incorrect POSIX acl buffer size "
9530 "(should be %u, was %u).\n",
9531 (unsigned int)expected_size
,
9532 (unsigned int)posix_acl_len
);
9537 * We don't need to know what the ACL's are
9538 * we just need to know we have at least 3
9539 * file entries (u,g,o).
9542 for (i
= 0; i
< num_file_acls
; i
++) {
9543 unsigned char tagtype
=
9545 SMB_POSIX_ACL_HEADER_SIZE
+
9546 (i
*SMB_POSIX_ACL_ENTRY_SIZE
));
9549 case SMB_POSIX_ACL_USER_OBJ
:
9552 case SMB_POSIX_ACL_GROUP_OBJ
:
9555 case SMB_POSIX_ACL_OTHER
:
9564 printf("Missing user entry\n");
9569 printf("Missing group entry\n");
9574 printf("Missing other entry\n");
9582 if (!torture_close_connection(cli
)) {
9586 printf("finished posix acl shareroot test\n");
9592 static uint32_t open_attrs_table
[] = {
9593 FILE_ATTRIBUTE_NORMAL
,
9594 FILE_ATTRIBUTE_ARCHIVE
,
9595 FILE_ATTRIBUTE_READONLY
,
9596 FILE_ATTRIBUTE_HIDDEN
,
9597 FILE_ATTRIBUTE_SYSTEM
,
9599 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
,
9600 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
,
9601 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
,
9602 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
,
9603 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
,
9604 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
,
9606 FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
,
9607 FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
,
9608 FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
,
9609 FILE_ATTRIBUTE_HIDDEN
,FILE_ATTRIBUTE_SYSTEM
,
9612 struct trunc_open_results
{
9615 uint32_t trunc_attr
;
9616 uint32_t result_attr
;
9619 static struct trunc_open_results attr_results
[] = {
9620 { 0, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_ARCHIVE
},
9621 { 1, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_ARCHIVE
},
9622 { 2, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_READONLY
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
},
9623 { 16, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_ARCHIVE
},
9624 { 17, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_ARCHIVE
},
9625 { 18, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_READONLY
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
},
9626 { 51, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9627 { 54, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9628 { 56, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
},
9629 { 68, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9630 { 71, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9631 { 73, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
},
9632 { 99, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_HIDDEN
,FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9633 { 102, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9634 { 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
},
9635 { 116, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9636 { 119, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9637 { 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
},
9638 { 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
},
9639 { 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
},
9640 { 227, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9641 { 230, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9642 { 232, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
},
9643 { 244, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9644 { 247, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9645 { 249, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
}
9648 static bool run_openattrtest(int dummy
)
9650 static struct cli_state
*cli1
;
9651 const char *fname
= "\\openattr.file";
9653 bool correct
= True
;
9655 unsigned int i
, j
, k
, l
;
9658 printf("starting open attr test\n");
9660 if (!torture_open_connection(&cli1
, 0)) {
9664 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
9666 for (k
= 0, i
= 0; i
< sizeof(open_attrs_table
)/sizeof(uint32_t); i
++) {
9667 cli_setatr(cli1
, fname
, 0, 0);
9668 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9670 status
= cli_ntcreate(cli1
, fname
, 0, FILE_WRITE_DATA
,
9671 open_attrs_table
[i
], FILE_SHARE_NONE
,
9672 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
9673 if (!NT_STATUS_IS_OK(status
)) {
9674 printf("open %d (1) of %s failed (%s)\n", i
, fname
, nt_errstr(status
));
9678 status
= cli_close(cli1
, fnum1
);
9679 if (!NT_STATUS_IS_OK(status
)) {
9680 printf("close %d (1) of %s failed (%s)\n", i
, fname
, nt_errstr(status
));
9684 for (j
= 0; j
< sizeof(open_attrs_table
)/sizeof(uint32_t); j
++) {
9685 status
= cli_ntcreate(cli1
, fname
, 0,
9686 FILE_READ_DATA
|FILE_WRITE_DATA
,
9687 open_attrs_table
[j
],
9688 FILE_SHARE_NONE
, FILE_OVERWRITE
,
9689 0, 0, &fnum1
, NULL
);
9690 if (!NT_STATUS_IS_OK(status
)) {
9691 for (l
= 0; l
< sizeof(attr_results
)/sizeof(struct trunc_open_results
); l
++) {
9692 if (attr_results
[l
].num
== k
) {
9693 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9694 k
, open_attrs_table
[i
],
9695 open_attrs_table
[j
],
9696 fname
, NT_STATUS_V(status
), nt_errstr(status
));
9701 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
9702 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9703 k
, open_attrs_table
[i
], open_attrs_table
[j
],
9708 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k
, open_attrs_table
[i
], open_attrs_table
[j
]);
9714 status
= cli_close(cli1
, fnum1
);
9715 if (!NT_STATUS_IS_OK(status
)) {
9716 printf("close %d (2) of %s failed (%s)\n", j
, fname
, nt_errstr(status
));
9720 status
= cli_getatr(cli1
, fname
, &attr
, NULL
, NULL
);
9721 if (!NT_STATUS_IS_OK(status
)) {
9722 printf("getatr(2) failed (%s)\n", nt_errstr(status
));
9727 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9728 k
, open_attrs_table
[i
], open_attrs_table
[j
], attr
);
9731 for (l
= 0; l
< sizeof(attr_results
)/sizeof(struct trunc_open_results
); l
++) {
9732 if (attr_results
[l
].num
== k
) {
9733 if (attr
!= attr_results
[l
].result_attr
||
9734 open_attrs_table
[i
] != attr_results
[l
].init_attr
||
9735 open_attrs_table
[j
] != attr_results
[l
].trunc_attr
) {
9736 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9737 open_attrs_table
[i
],
9738 open_attrs_table
[j
],
9740 attr_results
[l
].result_attr
);
9750 cli_setatr(cli1
, fname
, 0, 0);
9751 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9753 printf("open attr test %s.\n", correct
? "passed" : "failed");
9755 if (!torture_close_connection(cli1
)) {
9761 static NTSTATUS
list_fn(struct file_info
*finfo
,
9762 const char *name
, void *state
)
9764 int *matched
= (int *)state
;
9765 if (matched
!= NULL
) {
9768 return NT_STATUS_OK
;
9772 test directory listing speed
9774 static bool run_dirtest(int dummy
)
9777 static struct cli_state
*cli
;
9779 struct timeval core_start
;
9780 bool correct
= True
;
9783 printf("starting directory test\n");
9785 if (!torture_open_connection(&cli
, 0)) {
9789 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
9792 for (i
=0;i
<torture_numops
;i
++) {
9794 slprintf(fname
, sizeof(fname
), "\\%x", (int)random());
9795 if (!NT_STATUS_IS_OK(cli_openx(cli
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
, &fnum
))) {
9796 fprintf(stderr
,"Failed to open %s\n", fname
);
9799 cli_close(cli
, fnum
);
9802 core_start
= timeval_current();
9805 cli_list(cli
, "a*.*", 0, list_fn
, &matched
);
9806 printf("Matched %d\n", matched
);
9809 cli_list(cli
, "b*.*", 0, list_fn
, &matched
);
9810 printf("Matched %d\n", matched
);
9813 cli_list(cli
, "xyzabc", 0, list_fn
, &matched
);
9814 printf("Matched %d\n", matched
);
9816 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start
));
9819 for (i
=0;i
<torture_numops
;i
++) {
9821 slprintf(fname
, sizeof(fname
), "\\%x", (int)random());
9822 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9825 if (!torture_close_connection(cli
)) {
9829 printf("finished dirtest\n");
9834 static NTSTATUS
del_fn(struct file_info
*finfo
, const char *mask
,
9837 struct cli_state
*pcli
= (struct cli_state
*)state
;
9839 slprintf(fname
, sizeof(fname
), "\\LISTDIR\\%s", finfo
->name
);
9841 if (strcmp(finfo
->name
, ".") == 0 || strcmp(finfo
->name
, "..") == 0)
9842 return NT_STATUS_OK
;
9844 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
9845 if (!NT_STATUS_IS_OK(cli_rmdir(pcli
, fname
)))
9846 printf("del_fn: failed to rmdir %s\n,", fname
);
9848 if (!NT_STATUS_IS_OK(cli_unlink(pcli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
)))
9849 printf("del_fn: failed to unlink %s\n,", fname
);
9851 return NT_STATUS_OK
;
9856 sees what IOCTLs are supported
9858 bool torture_ioctl_test(int dummy
)
9860 static struct cli_state
*cli
;
9861 uint16_t device
, function
;
9863 const char *fname
= "\\ioctl.dat";
9867 if (!torture_open_connection(&cli
, 0)) {
9871 printf("starting ioctl test\n");
9873 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9875 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
9876 if (!NT_STATUS_IS_OK(status
)) {
9877 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
9881 status
= cli_raw_ioctl(cli
, fnum
, 0x2d0000 | (0x0420<<2), &blob
);
9882 printf("ioctl device info: %s\n", nt_errstr(status
));
9884 status
= cli_raw_ioctl(cli
, fnum
, IOCTL_QUERY_JOB_INFO
, &blob
);
9885 printf("ioctl job info: %s\n", nt_errstr(status
));
9887 for (device
=0;device
<0x100;device
++) {
9888 printf("ioctl test with device = 0x%x\n", device
);
9889 for (function
=0;function
<0x100;function
++) {
9890 uint32_t code
= (device
<<16) | function
;
9892 status
= cli_raw_ioctl(cli
, fnum
, code
, &blob
);
9894 if (NT_STATUS_IS_OK(status
)) {
9895 printf("ioctl 0x%x OK : %d bytes\n", (int)code
,
9897 data_blob_free(&blob
);
9902 if (!torture_close_connection(cli
)) {
9911 tries varients of chkpath
9913 bool torture_chkpath_test(int dummy
)
9915 static struct cli_state
*cli
;
9920 if (!torture_open_connection(&cli
, 0)) {
9924 printf("starting chkpath test\n");
9926 /* cleanup from an old run */
9927 torture_deltree(cli
, "\\chkpath.dir");
9929 status
= cli_mkdir(cli
, "\\chkpath.dir");
9930 if (!NT_STATUS_IS_OK(status
)) {
9931 printf("mkdir1 failed : %s\n", nt_errstr(status
));
9935 status
= cli_mkdir(cli
, "\\chkpath.dir\\dir2");
9936 if (!NT_STATUS_IS_OK(status
)) {
9937 printf("mkdir2 failed : %s\n", nt_errstr(status
));
9941 status
= cli_openx(cli
, "\\chkpath.dir\\foo.txt", O_RDWR
|O_CREAT
|O_EXCL
,
9943 if (!NT_STATUS_IS_OK(status
)) {
9944 printf("open1 failed (%s)\n", nt_errstr(status
));
9947 cli_close(cli
, fnum
);
9949 status
= cli_chkpath(cli
, "\\chkpath.dir");
9950 if (!NT_STATUS_IS_OK(status
)) {
9951 printf("chkpath1 failed: %s\n", nt_errstr(status
));
9955 status
= cli_chkpath(cli
, "\\chkpath.dir\\dir2");
9956 if (!NT_STATUS_IS_OK(status
)) {
9957 printf("chkpath2 failed: %s\n", nt_errstr(status
));
9961 status
= cli_chkpath(cli
, "\\chkpath.dir\\foo.txt");
9962 if (!NT_STATUS_IS_OK(status
)) {
9963 ret
= check_error(__LINE__
, status
, ERRDOS
, ERRbadpath
,
9964 NT_STATUS_NOT_A_DIRECTORY
);
9966 printf("* chkpath on a file should fail\n");
9970 status
= cli_chkpath(cli
, "\\chkpath.dir\\bar.txt");
9971 if (!NT_STATUS_IS_OK(status
)) {
9972 ret
= check_error(__LINE__
, status
, ERRDOS
, ERRbadfile
,
9973 NT_STATUS_OBJECT_NAME_NOT_FOUND
);
9975 printf("* chkpath on a non existent file should fail\n");
9979 status
= cli_chkpath(cli
, "\\chkpath.dir\\dirxx\\bar.txt");
9980 if (!NT_STATUS_IS_OK(status
)) {
9981 ret
= check_error(__LINE__
, status
, ERRDOS
, ERRbadpath
,
9982 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
9984 printf("* chkpath on a non existent component should fail\n");
9988 torture_deltree(cli
, "\\chkpath.dir");
9990 if (!torture_close_connection(cli
)) {
9997 static bool run_eatest(int dummy
)
9999 static struct cli_state
*cli
;
10000 const char *fname
= "\\eatest.txt";
10001 bool correct
= True
;
10004 struct ea_struct
*ea_list
= NULL
;
10005 TALLOC_CTX
*mem_ctx
= talloc_init("eatest");
10008 printf("starting eatest\n");
10010 if (!torture_open_connection(&cli
, 0)) {
10011 talloc_destroy(mem_ctx
);
10015 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
10017 status
= cli_ntcreate(cli
, fname
, 0,
10018 FIRST_DESIRED_ACCESS
, FILE_ATTRIBUTE_ARCHIVE
,
10019 FILE_SHARE_NONE
, FILE_OVERWRITE_IF
,
10020 0x4044, 0, &fnum
, NULL
);
10021 if (!NT_STATUS_IS_OK(status
)) {
10022 printf("open failed - %s\n", nt_errstr(status
));
10023 talloc_destroy(mem_ctx
);
10027 for (i
= 0; i
< 10; i
++) {
10028 fstring ea_name
, ea_val
;
10030 slprintf(ea_name
, sizeof(ea_name
), "EA_%zu", i
);
10031 memset(ea_val
, (char)i
+1, i
+1);
10032 status
= cli_set_ea_fnum(cli
, fnum
, ea_name
, ea_val
, i
+1);
10033 if (!NT_STATUS_IS_OK(status
)) {
10034 printf("ea_set of name %s failed - %s\n", ea_name
,
10035 nt_errstr(status
));
10036 talloc_destroy(mem_ctx
);
10041 cli_close(cli
, fnum
);
10042 for (i
= 0; i
< 10; i
++) {
10043 fstring ea_name
, ea_val
;
10045 slprintf(ea_name
, sizeof(ea_name
), "EA_%zu", i
+10);
10046 memset(ea_val
, (char)i
+1, i
+1);
10047 status
= cli_set_ea_path(cli
, fname
, ea_name
, ea_val
, i
+1);
10048 if (!NT_STATUS_IS_OK(status
)) {
10049 printf("ea_set of name %s failed - %s\n", ea_name
,
10050 nt_errstr(status
));
10051 talloc_destroy(mem_ctx
);
10056 status
= cli_get_ea_list_path(cli
, fname
, mem_ctx
, &num_eas
, &ea_list
);
10057 if (!NT_STATUS_IS_OK(status
)) {
10058 printf("ea_get list failed - %s\n", nt_errstr(status
));
10062 printf("num_eas = %d\n", (int)num_eas
);
10064 if (num_eas
!= 20) {
10065 printf("Should be 20 EA's stored... failing.\n");
10069 for (i
= 0; i
< num_eas
; i
++) {
10070 printf("%zu: ea_name = %s. Val = ", i
, ea_list
[i
].name
);
10071 dump_data(0, ea_list
[i
].value
.data
,
10072 ea_list
[i
].value
.length
);
10075 /* Setting EA's to zero length deletes them. Test this */
10076 printf("Now deleting all EA's - case indepenent....\n");
10079 cli_set_ea_path(cli
, fname
, "", "", 0);
10081 for (i
= 0; i
< 20; i
++) {
10083 slprintf(ea_name
, sizeof(ea_name
), "ea_%d", i
);
10084 status
= cli_set_ea_path(cli
, fname
, ea_name
, "", 0);
10085 if (!NT_STATUS_IS_OK(status
)) {
10086 printf("ea_set of name %s failed - %s\n", ea_name
,
10087 nt_errstr(status
));
10088 talloc_destroy(mem_ctx
);
10094 status
= cli_get_ea_list_path(cli
, fname
, mem_ctx
, &num_eas
, &ea_list
);
10095 if (!NT_STATUS_IS_OK(status
)) {
10096 printf("ea_get list failed - %s\n", nt_errstr(status
));
10100 printf("num_eas = %d\n", (int)num_eas
);
10101 for (i
= 0; i
< num_eas
; i
++) {
10102 printf("%zu: ea_name = %s. Val = ", i
, ea_list
[i
].name
);
10103 dump_data(0, ea_list
[i
].value
.data
,
10104 ea_list
[i
].value
.length
);
10107 if (num_eas
!= 0) {
10108 printf("deleting EA's failed.\n");
10112 /* Try and delete a non existent EA. */
10113 status
= cli_set_ea_path(cli
, fname
, "foo", "", 0);
10114 if (!NT_STATUS_IS_OK(status
)) {
10115 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10116 nt_errstr(status
));
10120 talloc_destroy(mem_ctx
);
10121 if (!torture_close_connection(cli
)) {
10128 static bool run_dirtest1(int dummy
)
10131 static struct cli_state
*cli
;
10134 bool correct
= True
;
10136 printf("starting directory test\n");
10138 if (!torture_open_connection(&cli
, 0)) {
10142 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
10144 cli_list(cli
, "\\LISTDIR\\*", 0, del_fn
, cli
);
10145 cli_list(cli
, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY
, del_fn
, cli
);
10146 cli_rmdir(cli
, "\\LISTDIR");
10147 cli_mkdir(cli
, "\\LISTDIR");
10149 /* Create 1000 files and 1000 directories. */
10150 for (i
=0;i
<1000;i
++) {
10152 slprintf(fname
, sizeof(fname
), "\\LISTDIR\\f%d", i
);
10153 if (!NT_STATUS_IS_OK(cli_ntcreate(cli
, fname
, 0, GENERIC_ALL_ACCESS
, FILE_ATTRIBUTE_ARCHIVE
,
10154 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OVERWRITE_IF
,
10155 0, 0, &fnum
, NULL
))) {
10156 fprintf(stderr
,"Failed to open %s\n", fname
);
10159 cli_close(cli
, fnum
);
10161 for (i
=0;i
<1000;i
++) {
10163 slprintf(fname
, sizeof(fname
), "\\LISTDIR\\d%d", i
);
10164 if (!NT_STATUS_IS_OK(cli_mkdir(cli
, fname
))) {
10165 fprintf(stderr
,"Failed to open %s\n", fname
);
10170 /* Now ensure that doing an old list sees both files and directories. */
10172 cli_list_old(cli
, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY
, list_fn
, &num_seen
);
10173 printf("num_seen = %d\n", num_seen
);
10174 /* We should see 100 files + 1000 directories + . and .. */
10175 if (num_seen
!= 2002)
10178 /* Ensure if we have the "must have" bits we only see the
10179 * relevent entries.
10182 cli_list_old(cli
, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY
<<8)|FILE_ATTRIBUTE_DIRECTORY
, list_fn
, &num_seen
);
10183 printf("num_seen = %d\n", num_seen
);
10184 if (num_seen
!= 1002)
10188 cli_list_old(cli
, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE
<<8)|FILE_ATTRIBUTE_DIRECTORY
, list_fn
, &num_seen
);
10189 printf("num_seen = %d\n", num_seen
);
10190 if (num_seen
!= 1000)
10193 /* Delete everything. */
10194 cli_list(cli
, "\\LISTDIR\\*", 0, del_fn
, cli
);
10195 cli_list(cli
, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY
, del_fn
, cli
);
10196 cli_rmdir(cli
, "\\LISTDIR");
10199 printf("Matched %d\n", cli_list(cli
, "a*.*", 0, list_fn
, NULL
));
10200 printf("Matched %d\n", cli_list(cli
, "b*.*", 0, list_fn
, NULL
));
10201 printf("Matched %d\n", cli_list(cli
, "xyzabc", 0, list_fn
, NULL
));
10204 if (!torture_close_connection(cli
)) {
10208 printf("finished dirtest1\n");
10213 static bool run_error_map_extract(int dummy
) {
10215 static struct cli_state
*c_dos
;
10216 static struct cli_state
*c_nt
;
10224 NTSTATUS nt_status
;
10228 /* NT-Error connection */
10230 disable_spnego
= true;
10231 if (!(c_nt
= open_nbt_connection())) {
10232 disable_spnego
= false;
10235 disable_spnego
= false;
10237 status
= smbXcli_negprot(c_nt
->conn
, c_nt
->timeout
, PROTOCOL_CORE
,
10240 if (!NT_STATUS_IS_OK(status
)) {
10241 printf("%s rejected the NT-error negprot (%s)\n", host
,
10242 nt_errstr(status
));
10243 cli_shutdown(c_nt
);
10247 status
= cli_session_setup_anon(c_nt
);
10248 if (!NT_STATUS_IS_OK(status
)) {
10249 printf("%s rejected the NT-error initial session setup (%s)\n",host
, nt_errstr(status
));
10253 /* DOS-Error connection */
10255 disable_spnego
= true;
10256 force_dos_errors
= true;
10257 if (!(c_dos
= open_nbt_connection())) {
10258 disable_spnego
= false;
10259 force_dos_errors
= false;
10262 disable_spnego
= false;
10263 force_dos_errors
= false;
10265 status
= smbXcli_negprot(c_dos
->conn
, c_dos
->timeout
, PROTOCOL_CORE
,
10267 if (!NT_STATUS_IS_OK(status
)) {
10268 printf("%s rejected the DOS-error negprot (%s)\n", host
,
10269 nt_errstr(status
));
10270 cli_shutdown(c_dos
);
10274 status
= cli_session_setup_anon(c_dos
);
10275 if (!NT_STATUS_IS_OK(status
)) {
10276 printf("%s rejected the DOS-error initial session setup (%s)\n",
10277 host
, nt_errstr(status
));
10281 c_nt
->map_dos_errors
= false;
10282 c_dos
->map_dos_errors
= false;
10284 for (error
=(0xc0000000 | 0x1); error
< (0xc0000000| 0xFFF); error
++) {
10285 struct cli_credentials
*user_creds
= NULL
;
10287 fstr_sprintf(user
, "%X", error
);
10289 user_creds
= cli_session_creds_init(talloc_tos(),
10294 false, /* use_kerberos */
10295 false, /* fallback_after_kerberos */
10296 false, /* use_ccache */
10297 false); /* password_is_nt_hash */
10298 if (user_creds
== NULL
) {
10299 printf("cli_session_creds_init(%s) failed\n", user
);
10303 status
= cli_session_setup_creds(c_nt
, user_creds
);
10304 if (NT_STATUS_IS_OK(status
)) {
10305 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10308 /* Case #1: 32-bit NT errors */
10309 if (!NT_STATUS_IS_DOS(status
)) {
10310 nt_status
= status
;
10312 printf("/** Dos error on NT connection! (%s) */\n",
10313 nt_errstr(status
));
10314 nt_status
= NT_STATUS(0xc0000000);
10317 status
= cli_session_setup_creds(c_dos
, user_creds
);
10318 if (NT_STATUS_IS_OK(status
)) {
10319 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10322 /* Case #1: 32-bit NT errors */
10323 if (NT_STATUS_IS_DOS(status
)) {
10324 printf("/** NT error on DOS connection! (%s) */\n",
10325 nt_errstr(status
));
10326 errnum
= errclass
= 0;
10328 errclass
= NT_STATUS_DOS_CLASS(status
);
10329 errnum
= NT_STATUS_DOS_CODE(status
);
10332 if (NT_STATUS_V(nt_status
) != error
) {
10333 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10334 get_nt_error_c_code(talloc_tos(), NT_STATUS(error
)),
10335 get_nt_error_c_code(talloc_tos(), nt_status
));
10338 printf("\t{%s,\t%s,\t%s},\n",
10339 smb_dos_err_class(errclass
),
10340 smb_dos_err_name(errclass
, errnum
),
10341 get_nt_error_c_code(talloc_tos(), NT_STATUS(error
)));
10343 TALLOC_FREE(user_creds
);
10348 static bool run_sesssetup_bench(int dummy
)
10350 static struct cli_state
*c
;
10351 const char *fname
= "\\file.dat";
10356 if (!torture_open_connection(&c
, 0)) {
10360 status
= cli_ntcreate(c
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
10361 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
10362 FILE_DELETE_ON_CLOSE
, 0, &fnum
, NULL
);
10363 if (!NT_STATUS_IS_OK(status
)) {
10364 d_printf("open %s failed: %s\n", fname
, nt_errstr(status
));
10368 for (i
=0; i
<torture_numops
; i
++) {
10369 status
= cli_session_setup_creds(c
, torture_creds
);
10370 if (!NT_STATUS_IS_OK(status
)) {
10371 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10372 __location__
, nt_errstr(status
));
10376 d_printf("\r%d ", (int)cli_state_get_uid(c
));
10378 status
= cli_ulogoff(c
);
10379 if (!NT_STATUS_IS_OK(status
)) {
10380 d_printf("(%s) cli_ulogoff failed: %s\n",
10381 __location__
, nt_errstr(status
));
10389 static bool subst_test(const char *str
, const char *user
, const char *domain
,
10390 uid_t uid
, gid_t gid
, const char *expected
)
10393 bool result
= true;
10395 subst
= talloc_sub_specified(talloc_tos(), str
, user
, NULL
, domain
, uid
, gid
);
10397 if (strcmp(subst
, expected
) != 0) {
10398 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10399 "[%s]\n", str
, user
, domain
, (int)uid
, (int)gid
, subst
,
10404 TALLOC_FREE(subst
);
10408 static void chain1_open_completion(struct tevent_req
*req
)
10412 status
= cli_openx_recv(req
, &fnum
);
10415 d_printf("cli_openx_recv returned %s: %d\n",
10417 NT_STATUS_IS_OK(status
) ? fnum
: -1);
10420 static void chain1_write_completion(struct tevent_req
*req
)
10424 status
= cli_write_andx_recv(req
, &written
);
10427 d_printf("cli_write_andx_recv returned %s: %d\n",
10429 NT_STATUS_IS_OK(status
) ? (int)written
: -1);
10432 static void chain1_close_completion(struct tevent_req
*req
)
10435 bool *done
= (bool *)tevent_req_callback_data_void(req
);
10437 status
= cli_close_recv(req
);
10442 d_printf("cli_close returned %s\n", nt_errstr(status
));
10445 static bool run_chain1(int dummy
)
10447 struct cli_state
*cli1
;
10448 struct tevent_context
*evt
= samba_tevent_context_init(NULL
);
10449 struct tevent_req
*reqs
[3], *smbreqs
[3];
10451 const char *str
= "foobar";
10452 const char *fname
= "\\test_chain";
10455 printf("starting chain1 test\n");
10456 if (!torture_open_connection(&cli1
, 0)) {
10460 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
10462 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
10464 reqs
[0] = cli_openx_create(talloc_tos(), evt
, cli1
, fname
,
10465 O_CREAT
|O_RDWR
, 0, &smbreqs
[0]);
10466 if (reqs
[0] == NULL
) return false;
10467 tevent_req_set_callback(reqs
[0], chain1_open_completion
, NULL
);
10470 reqs
[1] = cli_write_andx_create(talloc_tos(), evt
, cli1
, 0, 0,
10471 (const uint8_t *)str
, 0, strlen(str
)+1,
10472 smbreqs
, 1, &smbreqs
[1]);
10473 if (reqs
[1] == NULL
) return false;
10474 tevent_req_set_callback(reqs
[1], chain1_write_completion
, NULL
);
10476 reqs
[2] = cli_smb1_close_create(talloc_tos(), evt
, cli1
, 0, &smbreqs
[2]);
10477 if (reqs
[2] == NULL
) return false;
10478 tevent_req_set_callback(reqs
[2], chain1_close_completion
, &done
);
10480 status
= smb1cli_req_chain_submit(smbreqs
, ARRAY_SIZE(smbreqs
));
10481 if (!NT_STATUS_IS_OK(status
)) {
10486 tevent_loop_once(evt
);
10489 torture_close_connection(cli1
);
10493 static void chain2_sesssetup_completion(struct tevent_req
*req
)
10496 status
= cli_session_setup_guest_recv(req
);
10497 d_printf("sesssetup returned %s\n", nt_errstr(status
));
10500 static void chain2_tcon_completion(struct tevent_req
*req
)
10502 bool *done
= (bool *)tevent_req_callback_data_void(req
);
10504 status
= cli_tcon_andx_recv(req
);
10505 d_printf("tcon_and_x returned %s\n", nt_errstr(status
));
10509 static bool run_chain2(int dummy
)
10511 struct cli_state
*cli1
;
10512 struct tevent_context
*evt
= samba_tevent_context_init(NULL
);
10513 struct tevent_req
*reqs
[2], *smbreqs
[2];
10516 int flags
= CLI_FULL_CONNECTION_FORCE_SMB1
;
10518 printf("starting chain2 test\n");
10519 status
= cli_start_connection(&cli1
, lp_netbios_name(), host
, NULL
,
10520 port_to_use
, SMB_SIGNING_DEFAULT
, flags
);
10521 if (!NT_STATUS_IS_OK(status
)) {
10525 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
10527 reqs
[0] = cli_session_setup_guest_create(talloc_tos(), evt
, cli1
,
10529 if (reqs
[0] == NULL
) return false;
10530 tevent_req_set_callback(reqs
[0], chain2_sesssetup_completion
, NULL
);
10532 reqs
[1] = cli_tcon_andx_create(talloc_tos(), evt
, cli1
, "IPC$",
10533 "?????", NULL
, 0, &smbreqs
[1]);
10534 if (reqs
[1] == NULL
) return false;
10535 tevent_req_set_callback(reqs
[1], chain2_tcon_completion
, &done
);
10537 status
= smb1cli_req_chain_submit(smbreqs
, ARRAY_SIZE(smbreqs
));
10538 if (!NT_STATUS_IS_OK(status
)) {
10543 tevent_loop_once(evt
);
10546 torture_close_connection(cli1
);
10551 struct torture_createdel_state
{
10552 struct tevent_context
*ev
;
10553 struct cli_state
*cli
;
10556 static void torture_createdel_created(struct tevent_req
*subreq
);
10557 static void torture_createdel_closed(struct tevent_req
*subreq
);
10559 static struct tevent_req
*torture_createdel_send(TALLOC_CTX
*mem_ctx
,
10560 struct tevent_context
*ev
,
10561 struct cli_state
*cli
,
10564 struct tevent_req
*req
, *subreq
;
10565 struct torture_createdel_state
*state
;
10567 req
= tevent_req_create(mem_ctx
, &state
,
10568 struct torture_createdel_state
);
10575 subreq
= cli_ntcreate_send(
10576 state
, ev
, cli
, name
, 0,
10577 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
10578 FILE_ATTRIBUTE_NORMAL
,
10579 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
10580 FILE_OPEN_IF
, FILE_DELETE_ON_CLOSE
,
10581 SMB2_IMPERSONATION_IMPERSONATION
, 0);
10583 if (tevent_req_nomem(subreq
, req
)) {
10584 return tevent_req_post(req
, ev
);
10586 tevent_req_set_callback(subreq
, torture_createdel_created
, req
);
10590 static void torture_createdel_created(struct tevent_req
*subreq
)
10592 struct tevent_req
*req
= tevent_req_callback_data(
10593 subreq
, struct tevent_req
);
10594 struct torture_createdel_state
*state
= tevent_req_data(
10595 req
, struct torture_createdel_state
);
10599 status
= cli_ntcreate_recv(subreq
, &fnum
, NULL
);
10600 TALLOC_FREE(subreq
);
10601 if (tevent_req_nterror(req
, status
)) {
10602 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10603 nt_errstr(status
)));
10607 subreq
= cli_close_send(state
, state
->ev
, state
->cli
, fnum
);
10608 if (tevent_req_nomem(subreq
, req
)) {
10611 tevent_req_set_callback(subreq
, torture_createdel_closed
, req
);
10614 static void torture_createdel_closed(struct tevent_req
*subreq
)
10616 struct tevent_req
*req
= tevent_req_callback_data(
10617 subreq
, struct tevent_req
);
10620 status
= cli_close_recv(subreq
);
10621 if (tevent_req_nterror(req
, status
)) {
10622 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status
)));
10625 tevent_req_done(req
);
10628 static NTSTATUS
torture_createdel_recv(struct tevent_req
*req
)
10630 return tevent_req_simple_recv_ntstatus(req
);
10633 struct torture_createdels_state
{
10634 struct tevent_context
*ev
;
10635 struct cli_state
*cli
;
10636 const char *base_name
;
10640 struct tevent_req
**reqs
;
10643 static void torture_createdels_done(struct tevent_req
*subreq
);
10645 static struct tevent_req
*torture_createdels_send(TALLOC_CTX
*mem_ctx
,
10646 struct tevent_context
*ev
,
10647 struct cli_state
*cli
,
10648 const char *base_name
,
10652 struct tevent_req
*req
;
10653 struct torture_createdels_state
*state
;
10656 req
= tevent_req_create(mem_ctx
, &state
,
10657 struct torture_createdels_state
);
10663 state
->base_name
= talloc_strdup(state
, base_name
);
10664 if (tevent_req_nomem(state
->base_name
, req
)) {
10665 return tevent_req_post(req
, ev
);
10667 state
->num_files
= MAX(num_parallel
, num_files
);
10669 state
->received
= 0;
10671 state
->reqs
= talloc_array(state
, struct tevent_req
*, num_parallel
);
10672 if (tevent_req_nomem(state
->reqs
, req
)) {
10673 return tevent_req_post(req
, ev
);
10676 for (i
=0; i
<num_parallel
; i
++) {
10679 name
= talloc_asprintf(state
, "%s%8.8d", state
->base_name
,
10681 if (tevent_req_nomem(name
, req
)) {
10682 return tevent_req_post(req
, ev
);
10684 state
->reqs
[i
] = torture_createdel_send(
10685 state
->reqs
, state
->ev
, state
->cli
, name
);
10686 if (tevent_req_nomem(state
->reqs
[i
], req
)) {
10687 return tevent_req_post(req
, ev
);
10689 name
= talloc_move(state
->reqs
[i
], &name
);
10690 tevent_req_set_callback(state
->reqs
[i
],
10691 torture_createdels_done
, req
);
10697 static void torture_createdels_done(struct tevent_req
*subreq
)
10699 struct tevent_req
*req
= tevent_req_callback_data(
10700 subreq
, struct tevent_req
);
10701 struct torture_createdels_state
*state
= tevent_req_data(
10702 req
, struct torture_createdels_state
);
10703 size_t i
, num_parallel
= talloc_array_length(state
->reqs
);
10707 status
= torture_createdel_recv(subreq
);
10708 if (!NT_STATUS_IS_OK(status
)){
10709 DEBUG(10, ("torture_createdel_recv returned %s\n",
10710 nt_errstr(status
)));
10711 TALLOC_FREE(subreq
);
10712 tevent_req_nterror(req
, status
);
10716 for (i
=0; i
<num_parallel
; i
++) {
10717 if (subreq
== state
->reqs
[i
]) {
10721 if (i
== num_parallel
) {
10722 DEBUG(10, ("received something we did not send\n"));
10723 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
10726 TALLOC_FREE(state
->reqs
[i
]);
10728 if (state
->sent
>= state
->num_files
) {
10729 tevent_req_done(req
);
10733 name
= talloc_asprintf(state
, "%s%8.8d", state
->base_name
,
10735 if (tevent_req_nomem(name
, req
)) {
10738 state
->reqs
[i
] = torture_createdel_send(state
->reqs
, state
->ev
,
10740 if (tevent_req_nomem(state
->reqs
[i
], req
)) {
10743 name
= talloc_move(state
->reqs
[i
], &name
);
10744 tevent_req_set_callback(state
->reqs
[i
], torture_createdels_done
, req
);
10748 static NTSTATUS
torture_createdels_recv(struct tevent_req
*req
)
10750 return tevent_req_simple_recv_ntstatus(req
);
10753 struct swallow_notify_state
{
10754 struct tevent_context
*ev
;
10755 struct cli_state
*cli
;
10757 uint32_t completion_filter
;
10759 bool (*fn
)(uint32_t action
, const char *name
, void *priv
);
10763 static void swallow_notify_done(struct tevent_req
*subreq
);
10765 static struct tevent_req
*swallow_notify_send(TALLOC_CTX
*mem_ctx
,
10766 struct tevent_context
*ev
,
10767 struct cli_state
*cli
,
10769 uint32_t completion_filter
,
10771 bool (*fn
)(uint32_t action
,
10776 struct tevent_req
*req
, *subreq
;
10777 struct swallow_notify_state
*state
;
10779 req
= tevent_req_create(mem_ctx
, &state
,
10780 struct swallow_notify_state
);
10786 state
->fnum
= fnum
;
10787 state
->completion_filter
= completion_filter
;
10788 state
->recursive
= recursive
;
10790 state
->priv
= priv
;
10792 subreq
= cli_notify_send(state
, state
->ev
, state
->cli
, state
->fnum
,
10793 0xffff, state
->completion_filter
,
10795 if (tevent_req_nomem(subreq
, req
)) {
10796 return tevent_req_post(req
, ev
);
10798 tevent_req_set_callback(subreq
, swallow_notify_done
, req
);
10802 static void swallow_notify_done(struct tevent_req
*subreq
)
10804 struct tevent_req
*req
= tevent_req_callback_data(
10805 subreq
, struct tevent_req
);
10806 struct swallow_notify_state
*state
= tevent_req_data(
10807 req
, struct swallow_notify_state
);
10809 uint32_t i
, num_changes
;
10810 struct notify_change
*changes
;
10812 status
= cli_notify_recv(subreq
, state
, &num_changes
, &changes
);
10813 TALLOC_FREE(subreq
);
10814 if (!NT_STATUS_IS_OK(status
)) {
10815 DEBUG(10, ("cli_notify_recv returned %s\n",
10816 nt_errstr(status
)));
10817 tevent_req_nterror(req
, status
);
10821 for (i
=0; i
<num_changes
; i
++) {
10822 state
->fn(changes
[i
].action
, changes
[i
].name
, state
->priv
);
10824 TALLOC_FREE(changes
);
10826 subreq
= cli_notify_send(state
, state
->ev
, state
->cli
, state
->fnum
,
10827 0xffff, state
->completion_filter
,
10829 if (tevent_req_nomem(subreq
, req
)) {
10832 tevent_req_set_callback(subreq
, swallow_notify_done
, req
);
10835 static bool print_notifies(uint32_t action
, const char *name
, void *priv
)
10837 if (DEBUGLEVEL
> 5) {
10838 d_printf("%d %s\n", (int)action
, name
);
10843 static void notify_bench_done(struct tevent_req
*req
)
10845 int *num_finished
= (int *)tevent_req_callback_data_void(req
);
10846 *num_finished
+= 1;
10849 static bool run_notify_bench(int dummy
)
10851 const char *dname
= "\\notify-bench";
10852 struct tevent_context
*ev
;
10855 struct tevent_req
*req1
;
10856 struct tevent_req
*req2
= NULL
;
10857 int i
, num_unc_names
;
10858 int num_finished
= 0;
10860 printf("starting notify-bench test\n");
10862 if (use_multishare_conn
) {
10864 unc_list
= file_lines_load(multishare_conn_fname
,
10865 &num_unc_names
, 0, NULL
);
10866 if (!unc_list
|| num_unc_names
<= 0) {
10867 d_printf("Failed to load unc names list from '%s'\n",
10868 multishare_conn_fname
);
10871 TALLOC_FREE(unc_list
);
10876 ev
= samba_tevent_context_init(talloc_tos());
10878 d_printf("tevent_context_init failed\n");
10882 for (i
=0; i
<num_unc_names
; i
++) {
10883 struct cli_state
*cli
;
10886 base_fname
= talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10888 if (base_fname
== NULL
) {
10892 if (!torture_open_connection(&cli
, i
)) {
10896 status
= cli_ntcreate(cli
, dname
, 0,
10897 MAXIMUM_ALLOWED_ACCESS
,
10898 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
|
10900 FILE_OPEN_IF
, FILE_DIRECTORY_FILE
, 0,
10903 if (!NT_STATUS_IS_OK(status
)) {
10904 d_printf("Could not create %s: %s\n", dname
,
10905 nt_errstr(status
));
10909 req1
= swallow_notify_send(talloc_tos(), ev
, cli
, dnum
,
10910 FILE_NOTIFY_CHANGE_FILE_NAME
|
10911 FILE_NOTIFY_CHANGE_DIR_NAME
|
10912 FILE_NOTIFY_CHANGE_ATTRIBUTES
|
10913 FILE_NOTIFY_CHANGE_LAST_WRITE
,
10914 false, print_notifies
, NULL
);
10915 if (req1
== NULL
) {
10916 d_printf("Could not create notify request\n");
10920 req2
= torture_createdels_send(talloc_tos(), ev
, cli
,
10921 base_fname
, 10, torture_numops
);
10922 if (req2
== NULL
) {
10923 d_printf("Could not create createdels request\n");
10926 TALLOC_FREE(base_fname
);
10928 tevent_req_set_callback(req2
, notify_bench_done
,
10932 while (num_finished
< num_unc_names
) {
10934 ret
= tevent_loop_once(ev
);
10936 d_printf("tevent_loop_once failed\n");
10941 if (!tevent_req_poll(req2
, ev
)) {
10942 d_printf("tevent_req_poll failed\n");
10945 status
= torture_createdels_recv(req2
);
10946 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status
));
10951 static bool run_mangle1(int dummy
)
10953 struct cli_state
*cli
;
10954 const char *fname
= "this_is_a_long_fname_to_be_mangled.txt";
10958 time_t change_time
, access_time
, write_time
;
10962 printf("starting mangle1 test\n");
10963 if (!torture_open_connection(&cli
, 0)) {
10967 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
10969 status
= cli_ntcreate(cli
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
10970 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
10971 0, 0, &fnum
, NULL
);
10972 if (!NT_STATUS_IS_OK(status
)) {
10973 d_printf("open %s failed: %s\n", fname
, nt_errstr(status
));
10976 cli_close(cli
, fnum
);
10978 status
= cli_qpathinfo_alt_name(cli
, fname
, alt_name
);
10979 if (!NT_STATUS_IS_OK(status
)) {
10980 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10981 nt_errstr(status
));
10984 d_printf("alt_name: %s\n", alt_name
);
10986 status
= cli_openx(cli
, alt_name
, O_RDONLY
, DENY_NONE
, &fnum
);
10987 if (!NT_STATUS_IS_OK(status
)) {
10988 d_printf("cli_openx(%s) failed: %s\n", alt_name
,
10989 nt_errstr(status
));
10992 cli_close(cli
, fnum
);
10994 status
= cli_qpathinfo1(cli
, alt_name
, &change_time
, &access_time
,
10995 &write_time
, &size
, &attr
);
10996 if (!NT_STATUS_IS_OK(status
)) {
10997 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name
,
10998 nt_errstr(status
));
11005 static NTSTATUS
mangle_illegal_list_shortname_fn(struct file_info
*f
,
11009 if (f
->short_name
== NULL
) {
11010 return NT_STATUS_OK
;
11013 if (strlen(f
->short_name
) == 0) {
11014 return NT_STATUS_OK
;
11017 printf("unexpected shortname: %s\n", f
->short_name
);
11019 return NT_STATUS_OBJECT_NAME_INVALID
;
11022 static NTSTATUS
mangle_illegal_list_name_fn(struct file_info
*f
,
11026 char *name
= state
;
11028 printf("name: %s\n", f
->name
);
11029 fstrcpy(name
, f
->name
);
11030 return NT_STATUS_OK
;
11033 static bool run_mangle_illegal(int dummy
)
11035 struct cli_state
*cli
= NULL
;
11036 struct cli_state
*cli_posix
= NULL
;
11037 const char *fname
= "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11038 const char *illegal_fname
= "MANGLE_ILLEGAL/foo:bar";
11039 char *mangled_path
= NULL
;
11045 printf("starting mangle-illegal test\n");
11047 if (!torture_open_connection(&cli
, 0)) {
11051 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11053 if (!torture_open_connection(&cli_posix
, 0)) {
11057 smbXcli_conn_set_sockopt(cli_posix
->conn
, sockops
);
11059 status
= torture_setup_unix_extensions(cli_posix
);
11060 if (!NT_STATUS_IS_OK(status
)) {
11064 cli_rmdir(cli
, "\\MANGLE_ILLEGAL");
11065 status
= cli_mkdir(cli
, "\\MANGLE_ILLEGAL");
11066 if (!NT_STATUS_IS_OK(status
)) {
11067 printf("mkdir1 failed : %s\n", nt_errstr(status
));
11072 * Create a file with illegal NTFS characters and test that we
11073 * get a usable mangled name
11076 cli_setatr(cli_posix
, illegal_fname
, 0, 0);
11077 cli_posix_unlink(cli_posix
, illegal_fname
);
11079 status
= cli_posix_open(cli_posix
, illegal_fname
, O_RDWR
|O_CREAT
|O_EXCL
,
11081 if (!NT_STATUS_IS_OK(status
)) {
11082 printf("POSIX create of %s failed (%s)\n",
11083 illegal_fname
, nt_errstr(status
));
11087 status
= cli_close(cli_posix
, fnum
);
11088 if (!NT_STATUS_IS_OK(status
)) {
11089 printf("close failed (%s)\n", nt_errstr(status
));
11093 status
= cli_list(cli
, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn
, &name
);
11094 if (!NT_STATUS_IS_OK(status
)) {
11095 d_printf("cli_list failed: %s\n", nt_errstr(status
));
11099 mangled_path
= talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name
);
11100 if (mangled_path
== NULL
) {
11104 status
= cli_openx(cli
, mangled_path
, O_RDONLY
, DENY_NONE
, &fnum
);
11105 if (!NT_STATUS_IS_OK(status
)) {
11106 d_printf("cli_openx(%s) failed: %s\n", mangled_path
, nt_errstr(status
));
11107 TALLOC_FREE(mangled_path
);
11110 TALLOC_FREE(mangled_path
);
11111 cli_close(cli
, fnum
);
11113 cli_setatr(cli_posix
, illegal_fname
, 0, 0);
11114 cli_posix_unlink(cli_posix
, illegal_fname
);
11117 * Create a file with a long name and check that we got *no* short name.
11120 status
= cli_ntcreate(cli
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
11121 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
11122 0, 0, &fnum
, NULL
);
11123 if (!NT_STATUS_IS_OK(status
)) {
11124 d_printf("open %s failed: %s\n", fname
, nt_errstr(status
));
11127 cli_close(cli
, fnum
);
11129 status
= cli_list(cli
, fname
, 0, mangle_illegal_list_shortname_fn
, &alt_name
);
11130 if (!NT_STATUS_IS_OK(status
)) {
11131 d_printf("cli_list failed\n");
11135 cli_unlink(cli
, fname
, 0);
11136 cli_rmdir(cli
, "\\MANGLE_ILLEGAL");
11138 if (!torture_close_connection(cli_posix
)) {
11142 if (!torture_close_connection(cli
)) {
11149 static size_t null_source(uint8_t *buf
, size_t n
, void *priv
)
11151 size_t *to_pull
= (size_t *)priv
;
11152 size_t thistime
= *to_pull
;
11154 thistime
= MIN(thistime
, n
);
11155 if (thistime
== 0) {
11159 memset(buf
, 0, thistime
);
11160 *to_pull
-= thistime
;
11164 static bool run_windows_write(int dummy
)
11166 struct cli_state
*cli1
;
11170 const char *fname
= "\\writetest.txt";
11171 struct timeval start_time
;
11176 printf("starting windows_write test\n");
11177 if (!torture_open_connection(&cli1
, 0)) {
11181 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
11182 if (!NT_STATUS_IS_OK(status
)) {
11183 printf("open failed (%s)\n", nt_errstr(status
));
11187 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
11189 start_time
= timeval_current();
11191 for (i
=0; i
<torture_numops
; i
++) {
11193 off_t start
= i
* torture_blocksize
;
11194 size_t to_pull
= torture_blocksize
- 1;
11196 status
= cli_writeall(cli1
, fnum
, 0, &c
,
11197 start
+ torture_blocksize
- 1, 1, NULL
);
11198 if (!NT_STATUS_IS_OK(status
)) {
11199 printf("cli_write failed: %s\n", nt_errstr(status
));
11203 status
= cli_push(cli1
, fnum
, 0, i
* torture_blocksize
, torture_blocksize
,
11204 null_source
, &to_pull
);
11205 if (!NT_STATUS_IS_OK(status
)) {
11206 printf("cli_push returned: %s\n", nt_errstr(status
));
11211 seconds
= timeval_elapsed(&start_time
);
11212 kbytes
= (double)torture_blocksize
* torture_numops
;
11215 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes
,
11216 (double)seconds
, (int)(kbytes
/seconds
));
11220 cli_close(cli1
, fnum
);
11221 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11222 torture_close_connection(cli1
);
11226 static size_t calc_expected_return(struct cli_state
*cli
, size_t len_requested
)
11228 size_t max_pdu
= 0x1FFFF;
11230 if (cli
->server_posix_capabilities
& CIFS_UNIX_LARGE_READ_CAP
) {
11231 max_pdu
= 0xFFFFFF;
11234 if (smb1cli_conn_signing_is_active(cli
->conn
)) {
11238 if (smb1cli_conn_encryption_on(cli
->conn
)) {
11239 max_pdu
= CLI_BUFFER_SIZE
;
11242 if ((len_requested
& 0xFFFF0000) == 0xFFFF0000) {
11243 len_requested
&= 0xFFFF;
11246 return MIN(len_requested
,
11247 max_pdu
- (MIN_SMB_SIZE
+ VWV(12) + 1 /* padding byte */));
11250 static bool check_read_call(struct cli_state
*cli
,
11253 size_t len_requested
)
11256 struct tevent_req
*subreq
= NULL
;
11257 ssize_t len_read
= 0;
11258 size_t len_expected
= 0;
11259 struct tevent_context
*ev
= NULL
;
11261 ev
= samba_tevent_context_init(talloc_tos());
11266 subreq
= cli_read_andx_send(talloc_tos(),
11273 if (!tevent_req_poll_ntstatus(subreq
, ev
, &status
)) {
11277 status
= cli_read_andx_recv(subreq
, &len_read
, &buf
);
11278 if (!NT_STATUS_IS_OK(status
)) {
11279 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status
));
11283 TALLOC_FREE(subreq
);
11286 len_expected
= calc_expected_return(cli
, len_requested
);
11288 if (len_expected
> 0x10000 && len_read
== 0x10000) {
11289 /* Windows servers only return a max of 0x10000,
11290 doesn't matter if you set CAP_LARGE_READX in
11291 the client sessionsetupX call or not. */
11292 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11293 (unsigned int)len_requested
);
11294 } else if (len_read
!= len_expected
) {
11295 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11296 (unsigned int)len_requested
,
11297 (unsigned int)len_read
,
11298 (unsigned int)len_expected
);
11301 d_printf("Correct read reply.\n");
11307 /* Test large readX variants. */
11308 static bool large_readx_tests(struct cli_state
*cli
,
11312 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11313 if (check_read_call(cli
, fnum
, buf
, 0xFFFF0001) == false) {
11316 /* A read of 0x10000 should return 0x10000 bytes. */
11317 if (check_read_call(cli
, fnum
, buf
, 0x10000) == false) {
11320 /* A read of 0x10000 should return 0x10001 bytes. */
11321 if (check_read_call(cli
, fnum
, buf
, 0x10001) == false) {
11324 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11325 the requested number of bytes. */
11326 if (check_read_call(cli
, fnum
, buf
, 0x1FFFF - (MIN_SMB_SIZE
+ VWV(12))) == false) {
11329 /* A read of 1MB should return 1MB bytes (on Samba). */
11330 if (check_read_call(cli
, fnum
, buf
, 0x100000) == false) {
11334 if (check_read_call(cli
, fnum
, buf
, 0x20001) == false) {
11337 if (check_read_call(cli
, fnum
, buf
, 0x22000001) == false) {
11340 if (check_read_call(cli
, fnum
, buf
, 0xFFFE0001) == false) {
11346 static bool run_large_readx(int dummy
)
11348 uint8_t *buf
= NULL
;
11349 struct cli_state
*cli1
= NULL
;
11350 struct cli_state
*cli2
= NULL
;
11351 bool correct
= false;
11352 const char *fname
= "\\large_readx.dat";
11354 uint16_t fnum1
= UINT16_MAX
;
11355 uint32_t normal_caps
= 0;
11356 size_t file_size
= 20*1024*1024;
11357 TALLOC_CTX
*frame
= talloc_stackframe();
11361 enum smb_signing_setting signing_setting
;
11362 enum protocol_types protocol
;
11366 .signing_setting
= SMB_SIGNING_IF_REQUIRED
,
11367 .protocol
= PROTOCOL_NT1
,
11369 .name
= "NT1 - SIGNING_REQUIRED",
11370 .signing_setting
= SMB_SIGNING_REQUIRED
,
11371 .protocol
= PROTOCOL_NT1
,
11375 printf("starting large_readx test\n");
11377 if (!torture_open_connection(&cli1
, 0)) {
11381 normal_caps
= smb1cli_conn_capabilities(cli1
->conn
);
11383 if (!(normal_caps
& CAP_LARGE_READX
)) {
11384 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11385 (unsigned int)normal_caps
);
11389 /* Create a file of size 4MB. */
11390 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
,
11391 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
11392 0, 0, &fnum1
, NULL
);
11394 if (!NT_STATUS_IS_OK(status
)) {
11395 d_printf("open %s failed: %s\n", fname
, nt_errstr(status
));
11399 /* Write file_size bytes. */
11400 buf
= talloc_zero_array(frame
, uint8_t, file_size
);
11405 status
= cli_writeall(cli1
,
11412 if (!NT_STATUS_IS_OK(status
)) {
11413 d_printf("cli_writeall failed: %s\n", nt_errstr(status
));
11417 status
= cli_close(cli1
, fnum1
);
11418 if (!NT_STATUS_IS_OK(status
)) {
11419 d_printf("cli_close failed: %s\n", nt_errstr(status
));
11423 fnum1
= UINT16_MAX
;
11425 for (i
=0; i
< ARRAY_SIZE(runs
); i
++) {
11426 enum smb_signing_setting saved_signing_setting
= signing_state
;
11427 uint16_t fnum2
= -1;
11430 (runs
[i
].signing_setting
== SMB_SIGNING_REQUIRED
))
11432 d_printf("skip[%u] - %s\n", (unsigned)i
, runs
[i
].name
);
11436 d_printf("run[%u] - %s\n", (unsigned)i
, runs
[i
].name
);
11438 signing_state
= runs
[i
].signing_setting
;
11439 cli2
= open_nbt_connection();
11440 signing_state
= saved_signing_setting
;
11441 if (cli2
== NULL
) {
11445 status
= smbXcli_negprot(cli2
->conn
,
11449 if (!NT_STATUS_IS_OK(status
)) {
11453 status
= cli_session_setup_creds(cli2
, torture_creds
);
11454 if (!NT_STATUS_IS_OK(status
)) {
11458 status
= cli_tree_connect(cli2
,
11462 if (!NT_STATUS_IS_OK(status
)) {
11466 cli_set_timeout(cli2
, 120000); /* set a really long timeout (2 minutes) */
11468 normal_caps
= smb1cli_conn_capabilities(cli2
->conn
);
11470 if (!(normal_caps
& CAP_LARGE_READX
)) {
11471 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11472 (unsigned int)normal_caps
);
11477 if (force_cli_encryption(cli2
, share
) == false) {
11480 } else if (SERVER_HAS_UNIX_CIFS(cli2
)) {
11481 uint16_t major
, minor
;
11482 uint32_t caplow
, caphigh
;
11484 status
= cli_unix_extensions_version(cli2
,
11486 &caplow
, &caphigh
);
11487 if (!NT_STATUS_IS_OK(status
)) {
11492 status
= cli_ntcreate(cli2
, fname
, 0, FILE_READ_DATA
,
11493 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OPEN
,
11494 0, 0, &fnum2
, NULL
);
11495 if (!NT_STATUS_IS_OK(status
)) {
11496 d_printf("Second open %s failed: %s\n", fname
, nt_errstr(status
));
11500 /* All reads must return less than file_size bytes. */
11501 if (!large_readx_tests(cli2
, fnum2
, buf
)) {
11505 status
= cli_close(cli2
, fnum2
);
11506 if (!NT_STATUS_IS_OK(status
)) {
11507 d_printf("cli_close failed: %s\n", nt_errstr(status
));
11512 if (!torture_close_connection(cli2
)) {
11519 printf("Success on large_readx test\n");
11524 if (!torture_close_connection(cli2
)) {
11530 if (fnum1
!= UINT16_MAX
) {
11531 status
= cli_close(cli1
, fnum1
);
11532 if (!NT_STATUS_IS_OK(status
)) {
11533 d_printf("cli_close failed: %s\n", nt_errstr(status
));
11535 fnum1
= UINT16_MAX
;
11538 status
= cli_unlink(cli1
, fname
,
11539 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11540 if (!NT_STATUS_IS_OK(status
)) {
11541 printf("unlink failed (%s)\n", nt_errstr(status
));
11544 if (!torture_close_connection(cli1
)) {
11549 TALLOC_FREE(frame
);
11551 printf("finished large_readx test\n");
11555 static NTSTATUS
msdfs_attribute_list_fn(struct file_info
*finfo
,
11557 void *private_data
)
11559 uint32_t *p_attr
= (uint32_t *)private_data
;
11561 if (strequal(finfo
->name
, test_filename
)) {
11562 *p_attr
= finfo
->attr
;
11565 return NT_STATUS_OK
;
11568 static bool run_msdfs_attribute(int dummy
)
11570 static struct cli_state
*cli
;
11571 bool correct
= false;
11575 printf("Starting MSDFS-ATTRIBUTE test\n");
11577 if (test_filename
== NULL
|| test_filename
[0] == '\0') {
11578 printf("MSDFS-ATTRIBUTE test "
11579 "needs -f filename-of-msdfs-link\n");
11584 * NB. We use torture_open_connection_flags() not
11585 * torture_open_connection() as the latter forces
11588 if (!torture_open_connection_flags(&cli
, 0, 0)) {
11592 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11594 status
= cli_list(cli
,
11596 FILE_ATTRIBUTE_DIRECTORY
,
11597 msdfs_attribute_list_fn
,
11600 if (!NT_STATUS_IS_OK(status
)) {
11601 printf("cli_list failed with %s\n",
11602 nt_errstr(status
));
11605 if ((attr
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0) {
11606 printf("file %s should have "
11607 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11609 (unsigned int)attr
);
11613 if ((attr
& FILE_ATTRIBUTE_DIRECTORY
) == 0) {
11614 printf("file %s should have "
11615 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11617 (unsigned int)attr
);
11625 torture_close_connection(cli
);
11629 static bool run_cli_echo(int dummy
)
11631 struct cli_state
*cli
;
11634 printf("starting cli_echo test\n");
11635 if (!torture_open_connection(&cli
, 0)) {
11638 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11640 status
= cli_echo(cli
, 5, data_blob_const("hello", 5));
11642 d_printf("cli_echo returned %s\n", nt_errstr(status
));
11644 torture_close_connection(cli
);
11645 return NT_STATUS_IS_OK(status
);
11648 static int splice_status(off_t written
, void *priv
)
11653 static bool run_cli_splice(int dummy
)
11655 uint8_t *buf
= NULL
;
11656 struct cli_state
*cli1
= NULL
;
11657 bool correct
= false;
11658 const char *fname_src
= "\\splice_src.dat";
11659 const char *fname_dst
= "\\splice_dst.dat";
11661 uint16_t fnum1
= UINT16_MAX
;
11662 uint16_t fnum2
= UINT16_MAX
;
11663 size_t file_size
= 2*1024*1024;
11664 size_t splice_size
= 1*1024*1024 + 713;
11665 uint8_t digest1
[16], digest2
[16];
11668 TALLOC_CTX
*frame
= talloc_stackframe();
11670 printf("starting cli_splice test\n");
11672 if (!torture_open_connection(&cli1
, 0)) {
11676 cli_unlink(cli1
, fname_src
,
11677 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11678 cli_unlink(cli1
, fname_dst
,
11679 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11681 /* Create a file */
11682 status
= cli_ntcreate(cli1
, fname_src
, 0, GENERIC_ALL_ACCESS
,
11683 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
11684 0, 0, &fnum1
, NULL
);
11686 if (!NT_STATUS_IS_OK(status
)) {
11687 d_printf("open %s failed: %s\n", fname_src
, nt_errstr(status
));
11691 /* Write file_size bytes - must be bigger than splice_size. */
11692 buf
= talloc_zero_array(frame
, uint8_t, file_size
);
11694 d_printf("talloc_fail\n");
11698 /* Fill it with random numbers. */
11699 generate_random_buffer(buf
, file_size
);
11701 /* MD5 the first 1MB + 713 bytes. */
11702 gnutls_hash_fast(GNUTLS_DIG_MD5
,
11707 status
= cli_writeall(cli1
,
11714 if (!NT_STATUS_IS_OK(status
)) {
11715 d_printf("cli_writeall failed: %s\n", nt_errstr(status
));
11719 status
= cli_ntcreate(cli1
, fname_dst
, 0, GENERIC_ALL_ACCESS
,
11720 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
11721 0, 0, &fnum2
, NULL
);
11723 if (!NT_STATUS_IS_OK(status
)) {
11724 d_printf("open %s failed: %s\n", fname_dst
, nt_errstr(status
));
11728 /* Now splice 1MB + 713 bytes. */
11729 status
= cli_splice(cli1
,
11740 if (!NT_STATUS_IS_OK(status
)) {
11741 d_printf("cli_splice failed: %s\n", nt_errstr(status
));
11745 /* Clear the old buffer. */
11746 memset(buf
, '\0', file_size
);
11748 /* Read the new file. */
11749 status
= cli_read(cli1
, fnum2
, (char *)buf
, 0, splice_size
, &nread
);
11750 if (!NT_STATUS_IS_OK(status
)) {
11751 d_printf("cli_read failed: %s\n", nt_errstr(status
));
11754 if (nread
!= splice_size
) {
11755 d_printf("bad read of 0x%x, should be 0x%x\n",
11756 (unsigned int)nread
,
11757 (unsigned int)splice_size
);
11761 /* MD5 the first 1MB + 713 bytes. */
11762 gnutls_hash_fast(GNUTLS_DIG_MD5
,
11767 /* Must be the same. */
11768 if (memcmp(digest1
, digest2
, 16) != 0) {
11769 d_printf("bad MD5 compare\n");
11774 printf("Success on cli_splice test\n");
11779 if (fnum1
!= UINT16_MAX
) {
11780 cli_close(cli1
, fnum1
);
11782 if (fnum2
!= UINT16_MAX
) {
11783 cli_close(cli1
, fnum2
);
11786 cli_unlink(cli1
, fname_src
,
11787 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11788 cli_unlink(cli1
, fname_dst
,
11789 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11791 if (!torture_close_connection(cli1
)) {
11796 TALLOC_FREE(frame
);
11800 static bool run_uid_regression_test(int dummy
)
11802 static struct cli_state
*cli
;
11805 bool correct
= True
;
11806 struct smbXcli_tcon
*tcon_copy
= NULL
;
11809 printf("starting uid regression test\n");
11811 if (!torture_open_connection(&cli
, 0)) {
11815 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11817 /* Ok - now save then logoff our current user. */
11818 old_vuid
= cli_state_get_uid(cli
);
11820 status
= cli_ulogoff(cli
);
11821 if (!NT_STATUS_IS_OK(status
)) {
11822 d_printf("(%s) cli_ulogoff failed: %s\n",
11823 __location__
, nt_errstr(status
));
11828 cli_state_set_uid(cli
, old_vuid
);
11830 /* Try an operation. */
11831 status
= cli_mkdir(cli
, "\\uid_reg_test");
11832 if (NT_STATUS_IS_OK(status
)) {
11833 d_printf("(%s) cli_mkdir succeeded\n",
11838 /* Should be bad uid. */
11839 if (!check_error(__LINE__
, status
, ERRSRV
, ERRbaduid
,
11840 NT_STATUS_USER_SESSION_DELETED
)) {
11846 old_cnum
= cli_state_get_tid(cli
);
11848 * This is an SMB1-only test.
11849 * Copy the tcon, not "save/restore".
11851 * In SMB1 the cli_tdis() below frees
11852 * cli->smb1.tcon so we need a copy
11853 * of the struct to put back for the
11854 * second tdis call with invalid vuid.
11856 * This is a test-only hack. Real client code
11857 * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11859 tcon_copy
= smbXcli_tcon_copy(cli
, cli
->smb1
.tcon
);
11860 if (tcon_copy
== NULL
) {
11865 /* Now try a SMBtdis with the invalid vuid set to zero. */
11866 cli_state_set_uid(cli
, 0);
11868 /* This should succeed. */
11869 status
= cli_tdis(cli
);
11871 if (NT_STATUS_IS_OK(status
)) {
11872 d_printf("First tdis with invalid vuid should succeed.\n");
11874 d_printf("First tdis failed (%s)\n", nt_errstr(status
));
11876 cli
->smb1
.tcon
= tcon_copy
;
11880 cli
->smb1
.tcon
= tcon_copy
;
11881 cli_state_set_uid(cli
, old_vuid
);
11882 cli_state_set_tid(cli
, old_cnum
);
11884 /* This should fail. */
11885 status
= cli_tdis(cli
);
11886 if (NT_STATUS_IS_OK(status
)) {
11887 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11891 /* Should be bad tid. */
11892 if (!check_error(__LINE__
, status
, ERRSRV
, ERRinvnid
,
11893 NT_STATUS_NETWORK_NAME_DELETED
)) {
11899 cli_rmdir(cli
, "\\uid_reg_test");
11908 static const char *illegal_chars
= "*\\/?<>|\":";
11909 static char force_shortname_chars
[] = " +,.[];=\177";
11911 static NTSTATUS
shortname_del_fn(struct file_info
*finfo
,
11912 const char *mask
, void *state
)
11914 struct cli_state
*pcli
= (struct cli_state
*)state
;
11916 NTSTATUS status
= NT_STATUS_OK
;
11918 slprintf(fname
, sizeof(fname
), "\\shortname\\%s", finfo
->name
);
11920 if (strcmp(finfo
->name
, ".") == 0 || strcmp(finfo
->name
, "..") == 0)
11921 return NT_STATUS_OK
;
11923 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
11924 status
= cli_rmdir(pcli
, fname
);
11925 if (!NT_STATUS_IS_OK(status
)) {
11926 printf("del_fn: failed to rmdir %s\n,", fname
);
11929 status
= cli_unlink(pcli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11930 if (!NT_STATUS_IS_OK(status
)) {
11931 printf("del_fn: failed to unlink %s\n,", fname
);
11943 static NTSTATUS
shortname_list_fn(struct file_info
*finfo
,
11944 const char *name
, void *state
)
11946 struct sn_state
*s
= (struct sn_state
*)state
;
11950 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11951 i
, finfo
->name
, finfo
->short_name
);
11954 if (strchr(force_shortname_chars
, i
)) {
11955 if (!finfo
->short_name
) {
11956 /* Shortname not created when it should be. */
11957 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11958 __location__
, finfo
->name
, i
);
11961 } else if (finfo
->short_name
){
11962 /* Shortname created when it should not be. */
11963 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11964 __location__
, finfo
->short_name
, finfo
->name
);
11968 return NT_STATUS_OK
;
11971 static bool run_shortname_test(int dummy
)
11973 static struct cli_state
*cli
;
11974 bool correct
= True
;
11980 printf("starting shortname test\n");
11982 if (!torture_open_connection(&cli
, 0)) {
11986 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11988 cli_list(cli
, "\\shortname\\*", 0, shortname_del_fn
, cli
);
11989 cli_list(cli
, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY
, shortname_del_fn
, cli
);
11990 cli_rmdir(cli
, "\\shortname");
11992 status
= cli_mkdir(cli
, "\\shortname");
11993 if (!NT_STATUS_IS_OK(status
)) {
11994 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11995 __location__
, nt_errstr(status
));
12000 if (strlcpy(fname
, "\\shortname\\", sizeof(fname
)) >= sizeof(fname
)) {
12004 if (strlcat(fname
, "test .txt", sizeof(fname
)) >= sizeof(fname
)) {
12011 for (i
= 32; i
< 128; i
++) {
12012 uint16_t fnum
= (uint16_t)-1;
12016 if (strchr(illegal_chars
, i
)) {
12021 status
= cli_ntcreate(cli
, fname
, 0, GENERIC_ALL_ACCESS
, FILE_ATTRIBUTE_NORMAL
,
12022 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
12023 FILE_OVERWRITE_IF
, 0, 0, &fnum
, NULL
);
12024 if (!NT_STATUS_IS_OK(status
)) {
12025 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12026 __location__
, fname
, nt_errstr(status
));
12030 cli_close(cli
, fnum
);
12033 status
= cli_list(cli
, "\\shortname\\test*.*", 0,
12034 shortname_list_fn
, &s
);
12035 if (s
.matched
!= 1) {
12036 d_printf("(%s) failed to list %s: %s\n",
12037 __location__
, fname
, nt_errstr(status
));
12042 status
= cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
12043 if (!NT_STATUS_IS_OK(status
)) {
12044 d_printf("(%s) failed to delete %s: %s\n",
12045 __location__
, fname
, nt_errstr(status
));
12058 cli_list(cli
, "\\shortname\\*", 0, shortname_del_fn
, cli
);
12059 cli_list(cli
, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY
, shortname_del_fn
, cli
);
12060 cli_rmdir(cli
, "\\shortname");
12061 torture_close_connection(cli
);
12065 TLDAPRC callback_code
;
12067 static void pagedsearch_cb(struct tevent_req
*req
)
12070 struct tldap_message
*msg
;
12073 rc
= tldap_search_paged_recv(req
, talloc_tos(), &msg
);
12074 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12075 d_printf("tldap_search_paged_recv failed: %s\n",
12076 tldap_rc2string(rc
));
12077 callback_code
= rc
;
12080 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
12084 if (!tldap_entry_dn(msg
, &dn
)) {
12085 d_printf("tldap_entry_dn failed\n");
12088 d_printf("%s\n", dn
);
12092 enum tldap_extended_val
{
12099 * Construct an extended dn control with either no value, 0 or 1
12101 * No value and 0 are equivalent (non-hyphenated GUID)
12102 * 1 has the hyphenated GUID
12104 static struct tldap_control
*
12105 tldap_build_extended_control(enum tldap_extended_val val
)
12107 struct tldap_control empty_control
;
12108 struct asn1_data
*data
;
12110 ZERO_STRUCT(empty_control
);
12112 if (val
!= EXTENDED_NONE
) {
12113 data
= asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH
);
12119 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) {
12123 if (!asn1_write_Integer(data
, (int)val
)) {
12127 if (!asn1_pop_tag(data
)) {
12131 if (!asn1_blob(data
, &empty_control
.value
)) {
12136 empty_control
.oid
= "1.2.840.113556.1.4.529";
12137 empty_control
.critical
= true;
12139 return tldap_add_control(talloc_tos(), NULL
, 0, &empty_control
);
12143 static bool tldap_test_dn_guid_format(struct tldap_context
*ld
, const char *basedn
,
12144 enum tldap_extended_val control_val
)
12146 struct tldap_control
*control
= tldap_build_extended_control(control_val
);
12148 struct tldap_message
**msg
;
12151 rc
= tldap_search(ld
, basedn
, TLDAP_SCOPE_BASE
,
12152 "(objectClass=*)", NULL
, 0, 0,
12154 0, 0, 0, 0, talloc_tos(), &msg
);
12155 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12156 d_printf("tldap_search for domain DN failed: %s\n",
12157 tldap_errstr(talloc_tos(), ld
, rc
));
12161 if (!tldap_entry_dn(msg
[0], &dn
)) {
12162 d_printf("tldap_search domain DN fetch failed: %s\n",
12163 tldap_errstr(talloc_tos(), ld
, rc
));
12167 d_printf("%s\n", dn
);
12170 uint32_t time_mid
, time_hi_and_version
;
12171 uint32_t clock_seq
[2];
12175 switch (control_val
) {
12176 case EXTENDED_NONE
:
12177 case EXTENDED_ZERO
:
12179 * When reading GUIDs with hyphens, scanf will treat
12180 * hyphen as a hex character (and counts as part of the
12181 * width). This creates leftover GUID string which we
12182 * check will for with 'next' and closing '>'.
12184 if (12 == sscanf(dn
, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12185 &time_low
, &time_mid
,
12186 &time_hi_and_version
, &clock_seq
[0],
12187 &clock_seq
[1], &node
[0], &node
[1],
12188 &node
[2], &node
[3], &node
[4],
12189 &node
[5], &next
)) {
12190 /* This GUID is good */
12192 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12198 if (12 == sscanf(dn
,
12199 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12200 &time_low
, &time_mid
,
12201 &time_hi_and_version
, &clock_seq
[0],
12202 &clock_seq
[1], &node
[0], &node
[1],
12203 &node
[2], &node
[3], &node
[4],
12204 &node
[5], &next
)) {
12205 /* This GUID is good */
12207 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12220 static bool run_tldap(int dummy
)
12222 struct tldap_context
*ld
;
12226 struct sockaddr_storage addr
;
12227 struct tevent_context
*ev
;
12228 struct tevent_req
*req
;
12230 const char *filter
;
12232 if (!resolve_name(host
, &addr
, 0, false)) {
12233 d_printf("could not find host %s\n", host
);
12236 status
= open_socket_out(&addr
, 389, 9999, &fd
);
12237 if (!NT_STATUS_IS_OK(status
)) {
12238 d_printf("open_socket_out failed: %s\n", nt_errstr(status
));
12242 ld
= tldap_context_create(talloc_tos(), fd
);
12245 d_printf("tldap_context_create failed\n");
12249 rc
= tldap_fetch_rootdse(ld
);
12250 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12251 d_printf("tldap_fetch_rootdse failed: %s\n",
12252 tldap_errstr(talloc_tos(), ld
, rc
));
12256 basedn
= tldap_talloc_single_attribute(
12257 tldap_rootdse(ld
), "defaultNamingContext", talloc_tos());
12258 if (basedn
== NULL
) {
12259 d_printf("no defaultNamingContext\n");
12262 d_printf("defaultNamingContext: %s\n", basedn
);
12264 ev
= samba_tevent_context_init(talloc_tos());
12266 d_printf("tevent_context_init failed\n");
12270 rc
= tldap_gensec_bind(ld
, torture_creds
, "ldap", host
, NULL
,
12271 loadparm_init_s3(talloc_tos(),
12272 loadparm_s3_helpers()),
12273 GENSEC_FEATURE_SIGN
| GENSEC_FEATURE_SEAL
);
12275 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12276 d_printf("tldap_gensec_bind failed\n");
12280 callback_code
= TLDAP_SUCCESS
;
12282 req
= tldap_search_paged_send(talloc_tos(), ev
, ld
, basedn
,
12283 TLDAP_SCOPE_SUB
, "(objectclass=*)",
12285 NULL
, 0, NULL
, 0, 0, 0, 0, 5);
12287 d_printf("tldap_search_paged_send failed\n");
12290 tevent_req_set_callback(req
, pagedsearch_cb
, NULL
);
12292 tevent_req_poll(req
, ev
);
12296 rc
= callback_code
;
12298 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12299 d_printf("tldap_search with paging failed: %s\n",
12300 tldap_errstr(talloc_tos(), ld
, rc
));
12304 /* test search filters against rootDSE */
12305 filter
= "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12306 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12308 rc
= tldap_search(ld
, "", TLDAP_SCOPE_BASE
, filter
,
12309 NULL
, 0, 0, NULL
, 0, NULL
, 0, 0, 0, 0,
12310 talloc_tos(), NULL
);
12311 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12312 d_printf("tldap_search with complex filter failed: %s\n",
12313 tldap_errstr(talloc_tos(), ld
, rc
));
12318 * Tests to check for regression of:
12320 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12322 * TLDAP used here to pick apart the original string DN (with GUID)
12324 if (!tldap_test_dn_guid_format(ld
, basedn
, EXTENDED_NONE
)) {
12325 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12326 tldap_errstr(talloc_tos(), ld
, rc
));
12329 if (!tldap_test_dn_guid_format(ld
, basedn
, EXTENDED_ZERO
)) {
12330 d_printf("tldap_search with extended dn (0) failed: %s\n",
12331 tldap_errstr(talloc_tos(), ld
, rc
));
12334 if (!tldap_test_dn_guid_format(ld
, basedn
, EXTENDED_ONE
)) {
12335 d_printf("tldap_search with extended dn (1) failed: %s\n",
12336 tldap_errstr(talloc_tos(), ld
, rc
));
12344 /* Torture test to ensure no regression of :
12345 https://bugzilla.samba.org/show_bug.cgi?id=7084
12348 static bool run_dir_createtime(int dummy
)
12350 struct cli_state
*cli
;
12351 const char *dname
= "\\testdir_createtime";
12352 const char *fname
= "\\testdir_createtime\\testfile";
12354 struct timespec create_time
;
12355 struct timespec create_time1
;
12360 if (!torture_open_connection(&cli
, 0)) {
12364 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
12365 /* Ensure ino is zero, SMB2 gets a real one. */
12368 /* Ensure ino is -1, SMB1 never gets a real one. */
12369 ino
= (uint64_t)-1;
12372 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
12373 cli_rmdir(cli
, dname
);
12375 status
= cli_mkdir(cli
, dname
);
12376 if (!NT_STATUS_IS_OK(status
)) {
12377 printf("mkdir failed: %s\n", nt_errstr(status
));
12381 status
= cli_qpathinfo2(cli
, dname
, &create_time
, NULL
, NULL
, NULL
,
12383 if (!NT_STATUS_IS_OK(status
)) {
12384 printf("cli_qpathinfo2 returned %s\n",
12385 nt_errstr(status
));
12389 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
12390 /* SMB2 should always return an inode. */
12392 printf("SMB2 bad inode (0)\n");
12396 /* SMB1 must always return zero here. */
12398 printf("SMB1 bad inode (!0)\n");
12403 /* Sleep 3 seconds, then create a file. */
12406 status
= cli_openx(cli
, fname
, O_RDWR
| O_CREAT
| O_EXCL
,
12408 if (!NT_STATUS_IS_OK(status
)) {
12409 printf("cli_openx failed: %s\n", nt_errstr(status
));
12413 status
= cli_qpathinfo2(cli
, dname
, &create_time1
, NULL
, NULL
, NULL
,
12415 if (!NT_STATUS_IS_OK(status
)) {
12416 printf("cli_qpathinfo2 (2) returned %s\n",
12417 nt_errstr(status
));
12421 if (timespec_compare(&create_time1
, &create_time
)) {
12422 printf("run_dir_createtime: create time was updated (error)\n");
12424 printf("run_dir_createtime: create time was not updated (correct)\n");
12430 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
12431 cli_rmdir(cli
, dname
);
12432 if (!torture_close_connection(cli
)) {
12439 static bool run_streamerror(int dummy
)
12441 struct cli_state
*cli
;
12442 const char *dname
= "\\testdir_streamerror";
12443 const char *streamname
=
12444 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12446 time_t change_time
, access_time
, write_time
;
12452 if (!torture_open_connection(&cli
, 0)) {
12456 torture_deltree(cli
, dname
);
12458 status
= cli_mkdir(cli
, dname
);
12459 if (!NT_STATUS_IS_OK(status
)) {
12460 printf("mkdir failed: %s\n", nt_errstr(status
));
12464 status
= cli_qpathinfo1(cli
, streamname
, &change_time
, &access_time
,
12465 &write_time
, &size
, &attr
);
12466 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
12467 printf("pathinfo returned %s, expected "
12468 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12469 nt_errstr(status
));
12473 status
= cli_ntcreate(cli
, streamname
, 0x16,
12474 FILE_READ_DATA
|FILE_READ_EA
|
12475 FILE_READ_ATTRIBUTES
|READ_CONTROL_ACCESS
,
12476 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_READ
,
12477 FILE_OPEN
, 0, 0, &fnum
, NULL
);
12479 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
12480 printf("ntcreate returned %s, expected "
12481 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12482 nt_errstr(status
));
12487 cli_rmdir(cli
, dname
);
12491 struct pidtest_state
{
12497 static void pid_echo_done(struct tevent_req
*subreq
);
12499 static struct tevent_req
*pid_echo_send(TALLOC_CTX
*mem_ctx
,
12500 struct tevent_context
*ev
,
12501 struct cli_state
*cli
)
12503 struct tevent_req
*req
, *subreq
;
12504 struct pidtest_state
*state
;
12506 req
= tevent_req_create(mem_ctx
, &state
, struct pidtest_state
);
12511 SSVAL(state
->vwv
, 0, 1);
12512 state
->data
= data_blob_const("hello", 5);
12514 subreq
= smb1cli_req_send(state
,
12518 0, 0, /* *_flags */
12519 0, 0, /* *_flags2 */
12521 0xDEADBEEF, /* pid */
12523 NULL
, /* session */
12524 ARRAY_SIZE(state
->vwv
), state
->vwv
,
12525 state
->data
.length
, state
->data
.data
);
12527 if (tevent_req_nomem(subreq
, req
)) {
12528 return tevent_req_post(req
, ev
);
12530 tevent_req_set_callback(subreq
, pid_echo_done
, req
);
12534 static void pid_echo_done(struct tevent_req
*subreq
)
12536 struct tevent_req
*req
= tevent_req_callback_data(
12537 subreq
, struct tevent_req
);
12538 struct pidtest_state
*state
= tevent_req_data(
12539 req
, struct pidtest_state
);
12541 uint32_t num_bytes
;
12542 uint8_t *bytes
= NULL
;
12543 struct iovec
*recv_iov
= NULL
;
12544 uint8_t *phdr
= NULL
;
12545 uint16_t pidlow
= 0;
12546 uint16_t pidhigh
= 0;
12547 struct smb1cli_req_expected_response expected
[] = {
12549 .status
= NT_STATUS_OK
,
12554 status
= smb1cli_req_recv(subreq
, state
,
12559 NULL
, /* pvwv_offset */
12562 NULL
, /* pbytes_offset */
12564 expected
, ARRAY_SIZE(expected
));
12566 TALLOC_FREE(subreq
);
12568 if (!NT_STATUS_IS_OK(status
)) {
12569 tevent_req_nterror(req
, status
);
12573 if (num_bytes
!= state
->data
.length
) {
12574 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
12578 if (memcmp(bytes
, state
->data
.data
, num_bytes
) != 0) {
12579 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
12583 /* Check pid low/high == DEADBEEF */
12584 pidlow
= SVAL(phdr
, HDR_PID
);
12585 if (pidlow
!= 0xBEEF){
12586 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12587 (unsigned int)pidlow
);
12588 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
12591 pidhigh
= SVAL(phdr
, HDR_PIDHIGH
);
12592 if (pidhigh
!= 0xDEAD){
12593 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12594 (unsigned int)pidhigh
);
12595 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
12599 tevent_req_done(req
);
12602 static NTSTATUS
pid_echo_recv(struct tevent_req
*req
)
12604 return tevent_req_simple_recv_ntstatus(req
);
12607 static bool run_pidhigh(int dummy
)
12609 bool success
= false;
12610 struct cli_state
*cli
= NULL
;
12612 struct tevent_context
*ev
= NULL
;
12613 struct tevent_req
*req
= NULL
;
12614 TALLOC_CTX
*frame
= talloc_stackframe();
12616 printf("starting pid high test\n");
12617 if (!torture_open_connection(&cli
, 0)) {
12620 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
12622 ev
= samba_tevent_context_init(frame
);
12627 req
= pid_echo_send(frame
, ev
, cli
);
12632 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
12636 status
= pid_echo_recv(req
);
12637 if (NT_STATUS_IS_OK(status
)) {
12638 printf("pid high test ok\n");
12644 TALLOC_FREE(frame
);
12645 torture_close_connection(cli
);
12650 Test Windows open on a bad POSIX symlink.
12652 static bool run_symlink_open_test(int dummy
)
12654 static struct cli_state
*cli
;
12655 const char *fname
= "non_existant_file";
12656 const char *sname
= "dangling_symlink";
12657 uint16_t fnum
= (uint16_t)-1;
12658 bool correct
= false;
12660 TALLOC_CTX
*frame
= NULL
;
12662 frame
= talloc_stackframe();
12664 printf("Starting Windows bad symlink open test\n");
12666 if (!torture_open_connection(&cli
, 0)) {
12667 TALLOC_FREE(frame
);
12671 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
12673 status
= torture_setup_unix_extensions(cli
);
12674 if (!NT_STATUS_IS_OK(status
)) {
12675 TALLOC_FREE(frame
);
12679 /* Ensure nothing exists. */
12680 cli_setatr(cli
, fname
, 0, 0);
12681 cli_posix_unlink(cli
, fname
);
12682 cli_setatr(cli
, sname
, 0, 0);
12683 cli_posix_unlink(cli
, sname
);
12685 /* Create a symlink pointing nowhere. */
12686 status
= cli_posix_symlink(cli
, fname
, sname
);
12687 if (!NT_STATUS_IS_OK(status
)) {
12688 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12691 nt_errstr(status
));
12695 /* Now ensure that a Windows open doesn't hang. */
12696 status
= cli_ntcreate(cli
,
12699 FILE_READ_DATA
|FILE_WRITE_DATA
,
12701 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
12709 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12710 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12711 * we use O_NOFOLLOW on the server or not.
12713 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) ||
12714 NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
))
12718 printf("cli_ntcreate of %s returned %s - should return"
12719 " either (%s) or (%s)\n",
12722 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND
),
12723 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND
));
12731 if (fnum
!= (uint16_t)-1) {
12732 cli_close(cli
, fnum
);
12733 fnum
= (uint16_t)-1;
12736 cli_setatr(cli
, sname
, 0, 0);
12737 cli_posix_unlink(cli
, sname
);
12738 cli_setatr(cli
, fname
, 0, 0);
12739 cli_posix_unlink(cli
, fname
);
12741 if (!torture_close_connection(cli
)) {
12745 TALLOC_FREE(frame
);
12749 static NTSTATUS
smb1_wild_mangle_list_fn(struct file_info
*finfo
,
12753 char **mangled_name_return
= (char **)state
;
12754 bool is_mangled
= strchr(finfo
->name
, '~');
12757 *mangled_name_return
= talloc_strdup(NULL
, finfo
->name
);
12758 if (*mangled_name_return
== NULL
) {
12759 return NT_STATUS_NO_MEMORY
;
12762 return NT_STATUS_OK
;
12765 static bool run_smb1_wild_mangle_unlink_test(int dummy
)
12767 static struct cli_state
*cli_posix
= NULL
;
12768 static struct cli_state
*cli
= NULL
;
12769 uint16_t fnum
= (uint16_t)-1;
12770 bool correct
= false;
12771 const char *dname
= "smb1_wild_mangle_unlink";
12772 const char *aname
= "smb1_wild_mangle_unlink/a";
12773 const char *star_name
= "smb1_wild_mangle_unlink/*";
12774 char *windows_unlink_name
= NULL
;
12775 char *mangled_name
= NULL
;
12778 printf("Starting SMB1 wild mangle unlink test\n");
12780 /* Open a Windows connection. */
12781 if (!torture_open_connection(&cli
, 0)) {
12785 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
12787 /* Open a POSIX connection. */
12788 if (!torture_open_connection(&cli_posix
, 0)) {
12792 smbXcli_conn_set_sockopt(cli_posix
->conn
, sockops
);
12794 status
= torture_setup_unix_extensions(cli_posix
);
12795 if (!NT_STATUS_IS_OK(status
)) {
12796 printf("server doesn't support POSIX\n");
12801 torture_deltree(cli
, dname
);
12804 * Create two files - 'a' and '*'.
12805 * We need POSIX extensions for this as '*'
12806 * is not a valid Windows name.
12809 status
= cli_mkdir(cli
, dname
);
12810 if (!NT_STATUS_IS_OK(status
)) {
12811 printf("cli_mkdir of %s returned %s\n",
12813 nt_errstr(status
));
12817 status
= cli_posix_open(cli_posix
,
12819 O_RDWR
|O_CREAT
|O_EXCL
,
12822 if (!NT_STATUS_IS_OK(status
)) {
12823 printf("cli_posix_open (create) of %s returned %s\n",
12825 nt_errstr(status
));
12828 status
= cli_close(cli_posix
, fnum
);
12829 if (!NT_STATUS_IS_OK(status
)) {
12832 status
= cli_posix_open(cli_posix
,
12834 O_RDWR
|O_CREAT
|O_EXCL
,
12837 if (!NT_STATUS_IS_OK(status
)) {
12838 printf("cli_posix_open (create) of %s returned %s\n",
12840 nt_errstr(status
));
12843 status
= cli_close(cli_posix
, fnum
);
12844 if (!NT_STATUS_IS_OK(status
)) {
12848 status
= cli_list(cli
,
12851 smb1_wild_mangle_list_fn
,
12853 if (!NT_STATUS_IS_OK(status
)) {
12854 printf("cli_list of %s returned %s\n",
12856 nt_errstr(status
));
12860 if (mangled_name
== NULL
) {
12864 printf("mangled_name = %s\n",
12868 * Try a Windows unlink with the mangled name.
12869 * This should *NOT* unlink the 'a' name.
12872 windows_unlink_name
= talloc_asprintf(cli_posix
,
12877 status
= cli_unlink(cli
, windows_unlink_name
, 0);
12878 if (!NT_STATUS_IS_OK(status
)) {
12879 printf("cli_unlink of %s returned %s\n",
12880 windows_unlink_name
,
12881 nt_errstr(status
));
12885 /* Does 'a' still exist ? */
12886 status
= cli_posix_open(cli_posix
,
12891 if (!NT_STATUS_IS_OK(status
)) {
12892 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12894 nt_errstr(status
));
12898 status
= cli_close(cli_posix
, fnum
);
12899 if (!NT_STATUS_IS_OK(status
)) {
12907 TALLOC_FREE(windows_unlink_name
);
12908 TALLOC_FREE(mangled_name
);
12911 torture_deltree(cli
, dname
);
12912 torture_close_connection(cli
);
12915 if (cli_posix
!= NULL
) {
12916 torture_close_connection(cli_posix
);
12922 static bool run_smb1_wild_mangle_rename_test(int dummy
)
12924 static struct cli_state
*cli_posix
= NULL
;
12925 static struct cli_state
*cli
= NULL
;
12926 uint16_t fnum
= (uint16_t)-1;
12927 bool correct
= false;
12928 const char *dname
= "smb1_wild_mangle_rename";
12929 const char *fooname
= "smb1_wild_mangle_rename/foo";
12930 const char *foostar_name
= "smb1_wild_mangle_rename/fo*";
12931 const char *wild_name
= "smb1_wild_mangle_rename/*";
12932 char *windows_rename_src
= NULL
;
12933 const char *windows_rename_dst
= "smb1_wild_mangle_rename\\bar";
12934 char *mangled_name
= NULL
;
12937 printf("Starting SMB1 wild mangle rename test\n");
12939 if (!torture_open_connection(&cli_posix
, 0)) {
12943 smbXcli_conn_set_sockopt(cli_posix
->conn
, sockops
);
12945 status
= torture_setup_unix_extensions(cli_posix
);
12946 if (!NT_STATUS_IS_OK(status
)) {
12947 printf("server doesn't support POSIX\n");
12951 /* Open a Windows connection. */
12952 if (!torture_open_connection(&cli
, 0)) {
12956 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
12958 /* Ensure we start from fresh. */
12959 torture_deltree(cli
, dname
);
12962 * Create two files - 'foo' and 'fo*'.
12963 * We need POSIX extensions for this as 'fo*'
12964 * is not a valid Windows name.
12967 status
= cli_posix_mkdir(cli_posix
, dname
, 0770);
12968 if (!NT_STATUS_IS_OK(status
)) {
12969 printf("cli_posix_mkdir of %s returned %s\n",
12971 nt_errstr(status
));
12975 status
= cli_posix_open(cli_posix
,
12977 O_RDWR
|O_CREAT
|O_EXCL
,
12980 if (!NT_STATUS_IS_OK(status
)) {
12981 printf("cli_posix_open (create) of %s returned %s\n",
12983 nt_errstr(status
));
12986 status
= cli_close(cli_posix
, fnum
);
12987 if (!NT_STATUS_IS_OK(status
)) {
12990 status
= cli_posix_open(cli_posix
,
12992 O_RDWR
|O_CREAT
|O_EXCL
,
12995 if (!NT_STATUS_IS_OK(status
)) {
12996 printf("cli_posix_open (create) of %s returned %s\n",
12998 nt_errstr(status
));
13001 status
= cli_close(cli_posix
, fnum
);
13002 if (!NT_STATUS_IS_OK(status
)) {
13007 * Get the mangled name. We can re-use the
13008 * previous smb1_wild_mangle_list_fn for this.
13011 status
= cli_list(cli
,
13014 smb1_wild_mangle_list_fn
,
13016 if (!NT_STATUS_IS_OK(status
)) {
13017 printf("cli_list of %s returned %s\n",
13019 nt_errstr(status
));
13023 if (mangled_name
== NULL
) {
13027 printf("mangled_name = %s\n",
13031 * Try a Windows rename with the mangled name.
13032 * This should *NOT* rename the 'foo' name.
13035 windows_rename_src
= talloc_asprintf(cli_posix
,
13040 status
= cli_rename(cli
,
13041 windows_rename_src
,
13042 windows_rename_dst
,
13044 if (!NT_STATUS_IS_OK(status
)) {
13045 printf("cli_rename of %s -> %s returned %s\n",
13046 windows_rename_src
,
13047 windows_rename_dst
,
13048 nt_errstr(status
));
13052 /* Does 'foo' still exist ? */
13053 status
= cli_posix_open(cli_posix
,
13058 if (!NT_STATUS_IS_OK(status
)) {
13059 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13061 nt_errstr(status
));
13065 status
= cli_close(cli_posix
, fnum
);
13066 if (!NT_STATUS_IS_OK(status
)) {
13074 TALLOC_FREE(mangled_name
);
13075 TALLOC_FREE(windows_rename_src
);
13078 torture_deltree(cli
, dname
);
13079 torture_close_connection(cli
);
13082 torture_close_connection(cli_posix
);
13088 * Only testing minimal time strings, as the others
13089 * need (locale-dependent) guessing at what strftime does and
13090 * even may differ in builds.
13092 static bool timesubst_test(void)
13094 TALLOC_CTX
*ctx
= NULL
;
13095 /* Sa 23. Dez 04:33:20 CET 2017 */
13096 const struct timeval tv
= { 1514000000, 123 };
13097 const char* expect_minimal
= "20171223_033320";
13098 const char* expect_minus
= "20171223_033320_000123";
13100 char *env_tz
, *orig_tz
= NULL
;
13101 bool result
= true;
13103 ctx
= talloc_new(NULL
);
13105 env_tz
= getenv("TZ");
13107 orig_tz
= talloc_strdup(ctx
, env_tz
);
13109 setenv("TZ", "UTC", 1);
13111 s
= minimal_timeval_string(ctx
, &tv
, false);
13113 if(!s
|| strcmp(s
, expect_minimal
)) {
13114 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13115 "[%s]\n", s
? s
: "<nil>", expect_minimal
);
13119 s
= minimal_timeval_string(ctx
, &tv
, true);
13120 if(!s
|| strcmp(s
, expect_minus
)) {
13121 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13122 "[%s]\n", s
? s
: "<nil>", expect_minus
);
13128 setenv("TZ", orig_tz
, 1);
13135 static bool run_local_substitute(int dummy
)
13139 ok
&= subst_test("%U", "bla", "", -1, -1, "bla");
13140 ok
&= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13141 ok
&= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13142 ok
&= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13143 ok
&= subst_test("%g", "", "", -1, 0, gidtoname(0));
13144 ok
&= subst_test("%G", "", "", -1, 0, gidtoname(0));
13145 ok
&= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13146 ok
&= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13147 ok
&= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13148 /* Substitution depends on current time, so better test the underlying
13149 formatting function. At least covers %t. */
13150 ok
&= timesubst_test();
13152 /* Different captialization rules in sub_basic... */
13154 ok
&= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13160 static bool run_local_base64(int dummy
)
13165 for (i
=1; i
<2000; i
++) {
13166 DATA_BLOB blob1
, blob2
;
13169 blob1
.data
= talloc_array(talloc_tos(), uint8_t, i
);
13171 generate_random_buffer(blob1
.data
, blob1
.length
);
13173 b64
= base64_encode_data_blob(talloc_tos(), blob1
);
13175 d_fprintf(stderr
, "base64_encode_data_blob failed "
13176 "for %d bytes\n", i
);
13179 blob2
= base64_decode_data_blob(b64
);
13182 if (data_blob_cmp(&blob1
, &blob2
)) {
13183 d_fprintf(stderr
, "data_blob_cmp failed for %d "
13187 TALLOC_FREE(blob1
.data
);
13188 data_blob_free(&blob2
);
13193 static void parse_fn(const struct gencache_timeout
*t
,
13195 void *private_data
)
13200 static bool run_local_gencache(int dummy
)
13206 struct memcache
*mem
;
13209 mem
= memcache_init(NULL
, 0);
13211 d_printf("%s: memcache_init failed\n", __location__
);
13214 memcache_set_global(mem
);
13216 if (!gencache_set("foo", "bar", time(NULL
) + 1000)) {
13217 d_printf("%s: gencache_set() failed\n", __location__
);
13221 if (!gencache_get("foo", NULL
, NULL
, NULL
)) {
13222 d_printf("%s: gencache_get() failed\n", __location__
);
13226 for (i
=0; i
<1000000; i
++) {
13227 gencache_parse("foo", parse_fn
, NULL
);
13230 if (!gencache_get("foo", talloc_tos(), &val
, &tm
)) {
13231 d_printf("%s: gencache_get() failed\n", __location__
);
13236 if (!gencache_get("foo", talloc_tos(), &val
, &tm
)) {
13237 d_printf("%s: gencache_get() failed\n", __location__
);
13241 if (strcmp(val
, "bar") != 0) {
13242 d_printf("%s: gencache_get() returned %s, expected %s\n",
13243 __location__
, val
, "bar");
13250 if (!gencache_del("foo")) {
13251 d_printf("%s: gencache_del() failed\n", __location__
);
13254 if (gencache_del("foo")) {
13255 d_printf("%s: second gencache_del() succeeded\n",
13260 if (gencache_get("foo", talloc_tos(), &val
, &tm
)) {
13261 d_printf("%s: gencache_get() on deleted entry "
13262 "succeeded\n", __location__
);
13266 blob
= data_blob_string_const_null("bar");
13267 tm
= time(NULL
) + 60;
13269 if (!gencache_set_data_blob("foo", blob
, tm
)) {
13270 d_printf("%s: gencache_set_data_blob() failed\n", __location__
);
13274 if (!gencache_get_data_blob("foo", talloc_tos(), &blob
, NULL
, NULL
)) {
13275 d_printf("%s: gencache_get_data_blob() failed\n", __location__
);
13279 if (strcmp((const char *)blob
.data
, "bar") != 0) {
13280 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13281 __location__
, (const char *)blob
.data
, "bar");
13282 data_blob_free(&blob
);
13286 data_blob_free(&blob
);
13288 if (!gencache_del("foo")) {
13289 d_printf("%s: gencache_del() failed\n", __location__
);
13292 if (gencache_del("foo")) {
13293 d_printf("%s: second gencache_del() succeeded\n",
13298 if (gencache_get_data_blob("foo", talloc_tos(), &blob
, NULL
, NULL
)) {
13299 d_printf("%s: gencache_get_data_blob() on deleted entry "
13300 "succeeded\n", __location__
);
13305 blob
.data
= (uint8_t *)&v
;
13306 blob
.length
= sizeof(v
);
13308 if (!gencache_set_data_blob("blob", blob
, tm
)) {
13309 d_printf("%s: gencache_set_data_blob() failed\n",
13313 if (gencache_get("blob", talloc_tos(), &val
, &tm
)) {
13314 d_printf("%s: gencache_get succeeded\n", __location__
);
13321 static bool rbt_testflags(struct db_context
*db
, const char *key
,
13326 struct db_record
*rec
;
13328 rec
= dbwrap_fetch_locked(db
, db
, string_tdb_data(key
));
13330 d_fprintf(stderr
, "fetch_locked failed\n");
13334 status
= dbwrap_record_store(rec
, string_tdb_data(value
), TDB_MODIFY
);
13335 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
13336 d_fprintf(stderr
, "store TDB_MODIFY unexpected status: %s\n",
13337 nt_errstr(status
));
13341 status
= dbwrap_record_store(rec
, string_tdb_data("overwriteme"),
13343 if (!NT_STATUS_IS_OK(status
)) {
13344 d_fprintf(stderr
, "store TDB_INSERT failed: %s\n",
13345 nt_errstr(status
));
13349 status
= dbwrap_record_store(rec
, string_tdb_data(value
), TDB_INSERT
);
13350 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
13351 d_fprintf(stderr
, "store TDB_INSERT unexpected status: %s\n",
13352 nt_errstr(status
));
13356 status
= dbwrap_record_store(rec
, string_tdb_data(value
), TDB_MODIFY
);
13357 if (!NT_STATUS_IS_OK(status
)) {
13358 d_fprintf(stderr
, "store TDB_MODIFY failed: %s\n",
13359 nt_errstr(status
));
13369 static bool rbt_testval(struct db_context
*db
, const char *key
,
13372 struct db_record
*rec
;
13373 TDB_DATA data
= string_tdb_data(value
);
13378 rec
= dbwrap_fetch_locked(db
, db
, string_tdb_data(key
));
13380 d_fprintf(stderr
, "fetch_locked failed\n");
13383 status
= dbwrap_record_store(rec
, data
, 0);
13384 if (!NT_STATUS_IS_OK(status
)) {
13385 d_fprintf(stderr
, "store failed: %s\n", nt_errstr(status
));
13390 rec
= dbwrap_fetch_locked(db
, db
, string_tdb_data(key
));
13392 d_fprintf(stderr
, "second fetch_locked failed\n");
13396 dbvalue
= dbwrap_record_get_value(rec
);
13397 if ((dbvalue
.dsize
!= data
.dsize
)
13398 || (memcmp(dbvalue
.dptr
, data
.dptr
, data
.dsize
) != 0)) {
13399 d_fprintf(stderr
, "Got wrong data back\n");
13409 static int local_rbtree_traverse_read(struct db_record
*rec
, void *private_data
)
13411 int *count2
= (int *)private_data
;
13416 static int local_rbtree_traverse_delete(struct db_record
*rec
, void *private_data
)
13418 int *count2
= (int *)private_data
;
13420 dbwrap_record_delete(rec
);
13424 static bool run_local_rbtree(int dummy
)
13426 struct db_context
*db
;
13433 db
= db_open_rbt(NULL
);
13436 d_fprintf(stderr
, "db_open_rbt failed\n");
13440 if (!rbt_testflags(db
, "firstkey", "firstval")) {
13444 for (i
= 0; i
< 999; i
++) {
13445 char key
[sizeof("key-9223372036854775807")];
13446 char value
[sizeof("value-9223372036854775807")];
13448 snprintf(key
, sizeof(key
), "key%ld", random());
13449 snprintf(value
, sizeof(value
) ,"value%ld", random());
13451 if (!rbt_testval(db
, key
, value
)) {
13455 snprintf(value
, sizeof(value
) ,"value%ld", random());
13457 if (!rbt_testval(db
, key
, value
)) {
13463 count
= 0; count2
= 0;
13464 status
= dbwrap_traverse_read(db
, local_rbtree_traverse_read
,
13466 printf("%s: read1: %d %d, %s\n", __func__
, count
, count2
, nt_errstr(status
));
13467 if ((count
!= count2
) || (count
!= 1000)) {
13470 count
= 0; count2
= 0;
13471 status
= dbwrap_traverse(db
, local_rbtree_traverse_delete
,
13473 printf("%s: delete: %d %d, %s\n", __func__
, count
, count2
, nt_errstr(status
));
13474 if ((count
!= count2
) || (count
!= 1000)) {
13477 count
= 0; count2
= 0;
13478 status
= dbwrap_traverse_read(db
, local_rbtree_traverse_read
,
13480 printf("%s: read2: %d %d, %s\n", __func__
, count
, count2
, nt_errstr(status
));
13481 if ((count
!= count2
) || (count
!= 0)) {
13492 local test for character set functions
13494 This is a very simple test for the functionality in convert_string_error()
13496 static bool run_local_convert_string(int dummy
)
13498 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
13499 const char *test_strings
[2] = { "March", "M\303\244rz" };
13503 for (i
=0; i
<2; i
++) {
13504 const char *str
= test_strings
[i
];
13505 int len
= strlen(str
);
13506 size_t converted_size
;
13509 memset(dst
, 'X', sizeof(dst
));
13511 /* first try with real source length */
13512 ret
= convert_string_error(CH_UNIX
, CH_UTF8
,
13517 d_fprintf(stderr
, "Failed to convert '%s' to CH_DISPLAY\n", str
);
13521 if (converted_size
!= len
) {
13522 d_fprintf(stderr
, "Converted size of '%s' should be %d - got %d\n",
13523 str
, len
, (int)converted_size
);
13527 if (strncmp(str
, dst
, converted_size
) != 0) {
13528 d_fprintf(stderr
, "Expected '%s' to match '%s'\n", str
, dst
);
13532 if (strlen(str
) != converted_size
) {
13533 d_fprintf(stderr
, "Expected '%s' length %d - got %d\n", str
,
13534 (int)strlen(str
), (int)converted_size
);
13538 if (dst
[converted_size
] != 'X') {
13539 d_fprintf(stderr
, "Expected no termination of '%s'\n", dst
);
13543 /* now with srclen==-1, this causes the nul to be
13545 ret
= convert_string_error(CH_UNIX
, CH_UTF8
,
13550 d_fprintf(stderr
, "Failed to convert '%s' to CH_DISPLAY\n", str
);
13554 if (converted_size
!= len
+1) {
13555 d_fprintf(stderr
, "Converted size of '%s' should be %d - got %d\n",
13556 str
, len
, (int)converted_size
);
13560 if (strncmp(str
, dst
, converted_size
) != 0) {
13561 d_fprintf(stderr
, "Expected '%s' to match '%s'\n", str
, dst
);
13565 if (len
+1 != converted_size
) {
13566 d_fprintf(stderr
, "Expected '%s' length %d - got %d\n", str
,
13567 len
+1, (int)converted_size
);
13571 if (dst
[converted_size
] != 'X') {
13572 d_fprintf(stderr
, "Expected no termination of '%s'\n", dst
);
13579 TALLOC_FREE(tmp_ctx
);
13582 TALLOC_FREE(tmp_ctx
);
13586 static bool run_local_string_to_sid(int dummy
) {
13587 struct dom_sid sid
;
13589 if (string_to_sid(&sid
, "S--1-5-32-545")) {
13590 printf("allowing S--1-5-32-545\n");
13593 if (string_to_sid(&sid
, "S-1-5-32-+545")) {
13594 printf("allowing S-1-5-32-+545\n");
13597 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")) {
13598 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13601 if (string_to_sid(&sid
, "S-1-5-32-545-abc")) {
13602 printf("allowing S-1-5-32-545-abc\n");
13605 if (string_to_sid(&sid
, "S-300-5-32-545")) {
13606 printf("allowing S-300-5-32-545\n");
13609 if (string_to_sid(&sid
, "S-1-0xfffffffffffffe-32-545")) {
13610 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13613 if (string_to_sid(&sid
, "S-1-0xffffffffffff-5294967297-545")) {
13614 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13617 if (!string_to_sid(&sid
, "S-1-0xfffffffffffe-32-545")) {
13618 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13621 if (!string_to_sid(&sid
, "S-1-5-32-545")) {
13622 printf("could not parse S-1-5-32-545\n");
13625 if (!dom_sid_equal(&sid
, &global_sid_Builtin_Users
)) {
13626 struct dom_sid_buf buf
;
13627 printf("mis-parsed S-1-5-32-545 as %s\n",
13628 dom_sid_str_buf(&sid
, &buf
));
13634 static bool sid_to_string_test(const char *expected
) {
13637 struct dom_sid sid
;
13639 if (!string_to_sid(&sid
, expected
)) {
13640 printf("could not parse %s\n", expected
);
13644 str
= dom_sid_string(NULL
, &sid
);
13645 if (strcmp(str
, expected
)) {
13646 printf("Comparison failed (%s != %s)\n", str
, expected
);
13653 static bool run_local_sid_to_string(int dummy
) {
13654 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13656 if (!sid_to_string_test("S-1-545"))
13658 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13663 static bool run_local_binary_to_sid(int dummy
) {
13665 struct dom_sid
*sid
= talloc(NULL
, struct dom_sid
);
13666 static const uint8_t good_binary_sid
[] = {
13667 0x1, /* revision number */
13668 15, /* num auths */
13669 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13670 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13671 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13672 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13673 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13674 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13675 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13676 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13677 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13678 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13679 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13680 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13681 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13682 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13683 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13684 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13687 static const uint8_t long_binary_sid
[] = {
13688 0x1, /* revision number */
13689 15, /* num auths */
13690 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13691 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13692 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13693 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13694 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13695 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13696 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13697 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13698 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13699 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13700 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13701 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13702 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13703 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13704 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13705 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13706 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13707 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13708 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13711 static const uint8_t long_binary_sid2
[] = {
13712 0x1, /* revision number */
13713 32, /* num auths */
13714 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13715 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13716 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13717 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13718 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13719 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13720 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13721 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13722 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13723 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13724 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13725 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13726 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13727 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13728 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13729 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13730 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13731 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13732 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13733 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13734 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13735 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13736 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13737 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13738 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13739 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13740 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13741 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13742 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13743 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13744 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13745 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13746 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13749 ret
= sid_parse(good_binary_sid
, sizeof(good_binary_sid
), sid
);
13753 ret
= sid_parse(long_binary_sid2
, sizeof(long_binary_sid2
), sid
);
13757 ret
= sid_parse(long_binary_sid
, sizeof(long_binary_sid
), sid
);
13764 /* Split a path name into filename and stream name components. Canonicalise
13765 * such that an implicit $DATA token is always explicit.
13767 * The "specification" of this function can be found in the
13768 * run_local_stream_name() function in torture.c, I've tried those
13769 * combinations against a W2k3 server.
13772 static NTSTATUS
split_ntfs_stream_name(TALLOC_CTX
*mem_ctx
, const char *fname
,
13773 char **pbase
, char **pstream
)
13776 char *stream
= NULL
;
13777 char *sname
; /* stream name */
13778 const char *stype
; /* stream type */
13780 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname
));
13782 sname
= strchr_m(fname
, ':');
13784 if (sname
== NULL
) {
13785 if (pbase
!= NULL
) {
13786 base
= talloc_strdup(mem_ctx
, fname
);
13787 NT_STATUS_HAVE_NO_MEMORY(base
);
13792 if (pbase
!= NULL
) {
13793 base
= talloc_strndup(mem_ctx
, fname
, PTR_DIFF(sname
, fname
));
13794 NT_STATUS_HAVE_NO_MEMORY(base
);
13799 stype
= strchr_m(sname
, ':');
13801 if (stype
== NULL
) {
13802 sname
= talloc_strdup(mem_ctx
, sname
);
13806 if (strcasecmp_m(stype
, ":$DATA") != 0) {
13808 * If there is an explicit stream type, so far we only
13809 * allow $DATA. Is there anything else allowed? -- vl
13811 DEBUG(10, ("[%s] is an invalid stream type\n", stype
));
13813 return NT_STATUS_OBJECT_NAME_INVALID
;
13815 sname
= talloc_strndup(mem_ctx
, sname
, PTR_DIFF(stype
, sname
));
13819 if (sname
== NULL
) {
13821 return NT_STATUS_NO_MEMORY
;
13824 if (sname
[0] == '\0') {
13826 * no stream name, so no stream
13831 if (pstream
!= NULL
) {
13832 stream
= talloc_asprintf(mem_ctx
, "%s:%s", sname
, stype
);
13833 if (stream
== NULL
) {
13834 TALLOC_FREE(sname
);
13836 return NT_STATUS_NO_MEMORY
;
13839 * upper-case the type field
13841 (void)strupper_m(strchr_m(stream
, ':')+1);
13845 if (pbase
!= NULL
) {
13848 if (pstream
!= NULL
) {
13851 return NT_STATUS_OK
;
13854 static bool test_stream_name(const char *fname
, const char *expected_base
,
13855 const char *expected_stream
,
13856 NTSTATUS expected_status
)
13860 char *stream
= NULL
;
13862 status
= split_ntfs_stream_name(talloc_tos(), fname
, &base
, &stream
);
13863 if (!NT_STATUS_EQUAL(status
, expected_status
)) {
13867 if (!NT_STATUS_IS_OK(status
)) {
13871 if (base
== NULL
) goto error
;
13873 if (strcmp(expected_base
, base
) != 0) goto error
;
13875 if ((expected_stream
!= NULL
) && (stream
== NULL
)) goto error
;
13876 if ((expected_stream
== NULL
) && (stream
!= NULL
)) goto error
;
13878 if ((stream
!= NULL
) && (strcmp(expected_stream
, stream
) != 0))
13882 TALLOC_FREE(stream
);
13886 d_fprintf(stderr
, "Do test_stream(%s, %s, %s, %s)\n",
13887 fname
, expected_base
? expected_base
: "<NULL>",
13888 expected_stream
? expected_stream
: "<NULL>",
13889 nt_errstr(expected_status
));
13890 d_fprintf(stderr
, "-> base=%s, stream=%s, status=%s\n",
13891 base
? base
: "<NULL>", stream
? stream
: "<NULL>",
13892 nt_errstr(status
));
13894 TALLOC_FREE(stream
);
13898 static bool run_local_stream_name(int dummy
)
13902 ret
&= test_stream_name(
13903 "bla", "bla", NULL
, NT_STATUS_OK
);
13904 ret
&= test_stream_name(
13905 "bla::$DATA", "bla", NULL
, NT_STATUS_OK
);
13906 ret
&= test_stream_name(
13907 "bla:blub:", "bla", NULL
, NT_STATUS_OBJECT_NAME_INVALID
);
13908 ret
&= test_stream_name(
13909 "bla::", NULL
, NULL
, NT_STATUS_OBJECT_NAME_INVALID
);
13910 ret
&= test_stream_name(
13911 "bla::123", "bla", NULL
, NT_STATUS_OBJECT_NAME_INVALID
);
13912 ret
&= test_stream_name(
13913 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK
);
13914 ret
&= test_stream_name(
13915 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK
);
13916 ret
&= test_stream_name(
13917 "bla:x", "bla", "x:$DATA", NT_STATUS_OK
);
13922 static bool data_blob_equal(DATA_BLOB a
, DATA_BLOB b
)
13924 if (a
.length
!= b
.length
) {
13925 printf("a.length=%d != b.length=%d\n",
13926 (int)a
.length
, (int)b
.length
);
13929 if (memcmp(a
.data
, b
.data
, a
.length
) != 0) {
13930 printf("a.data and b.data differ\n");
13936 static bool run_local_memcache(int dummy
)
13938 struct memcache
*cache
;
13939 DATA_BLOB k1
, k2
, k3
, k4
, k5
;
13943 TALLOC_CTX
*mem_ctx
;
13949 size_t size1
, size2
;
13952 mem_ctx
= talloc_init("foo");
13953 if (mem_ctx
== NULL
) {
13957 /* STAT_CACHE TESTS */
13959 cache
= memcache_init(NULL
, sizeof(void *) == 8 ? 200 : 100);
13961 if (cache
== NULL
) {
13962 printf("memcache_init failed\n");
13966 d1
= data_blob_const("d1", 2);
13967 d3
= data_blob_const("d3", 2);
13969 k1
= data_blob_const("d1", 2);
13970 k2
= data_blob_const("d2", 2);
13971 k3
= data_blob_const("d3", 2);
13972 k4
= data_blob_const("d4", 2);
13973 k5
= data_blob_const("d5", 2);
13975 memcache_add(cache
, STAT_CACHE
, k1
, d1
);
13977 if (!memcache_lookup(cache
, STAT_CACHE
, k1
, &v1
)) {
13978 printf("could not find k1\n");
13981 if (!data_blob_equal(d1
, v1
)) {
13985 memcache_add(cache
, STAT_CACHE
, k1
, d3
);
13987 if (!memcache_lookup(cache
, STAT_CACHE
, k1
, &v3
)) {
13988 printf("could not find replaced k1\n");
13991 if (!data_blob_equal(d3
, v3
)) {
13995 TALLOC_FREE(cache
);
13997 /* GETWD_CACHE TESTS */
13998 str1
= talloc_strdup(mem_ctx
, "string1");
13999 if (str1
== NULL
) {
14002 ptr2
= str1
; /* Keep an alias for comparison. */
14004 str2
= talloc_strdup(mem_ctx
, "string2");
14005 if (str2
== NULL
) {
14009 cache
= memcache_init(NULL
, sizeof(void *) == 8 ? 200 : 100);
14010 if (cache
== NULL
) {
14011 printf("memcache_init failed\n");
14015 memcache_add_talloc(cache
, GETWD_CACHE
, k2
, &str1
);
14016 /* str1 == NULL now. */
14017 ptr1
= memcache_lookup_talloc(cache
, GETWD_CACHE
, k2
);
14018 if (ptr1
== NULL
) {
14019 printf("could not find k2\n");
14022 if (ptr1
!= ptr2
) {
14023 printf("fetch of k2 got wrong string\n");
14027 /* Add a blob to ensure k2 gets purged. */
14028 d3
= data_blob_talloc_zero(mem_ctx
, 180);
14029 memcache_add(cache
, STAT_CACHE
, k3
, d3
);
14031 ptr2
= memcache_lookup_talloc(cache
, GETWD_CACHE
, k2
);
14032 if (ptr2
!= NULL
) {
14033 printf("Did find k2, should have been purged\n");
14038 * Test that talloc size also is accounted in memcache and
14039 * causes purge of other object.
14042 str1
= talloc_zero_size(mem_ctx
, 100);
14043 str2
= talloc_zero_size(mem_ctx
, 100);
14045 memcache_add_talloc(cache
, GETWD_CACHE
, k4
, &str1
);
14046 memcache_add_talloc(cache
, GETWD_CACHE
, k5
, &str1
);
14048 ptr3
= memcache_lookup_talloc(cache
, GETWD_CACHE
, k4
);
14049 if (ptr3
!= NULL
) {
14050 printf("Did find k4, should have been purged\n");
14055 * Test that adding a duplicate non-talloced
14056 * key/value on top of a talloced key/value takes account
14057 * of the talloc_freed value size.
14059 TALLOC_FREE(cache
);
14060 TALLOC_FREE(mem_ctx
);
14062 mem_ctx
= talloc_init("key_replace");
14063 if (mem_ctx
== NULL
) {
14067 cache
= memcache_init(NULL
, sizeof(void *) == 8 ? 200 : 100);
14068 if (cache
== NULL
) {
14073 * Add a 100 byte talloced string. This will
14074 * store a (4 or 8 byte) pointer and record the
14075 * total talloced size.
14077 str1
= talloc_zero_size(mem_ctx
, 100);
14078 memcache_add_talloc(cache
, GETWD_CACHE
, k4
, &str1
);
14080 * Now overwrite with a small talloced
14081 * value. This should fit in the existing size
14082 * and the total talloced size should be removed
14083 * from the cache size.
14085 str1
= talloc_zero_size(mem_ctx
, 2);
14086 memcache_add_talloc(cache
, GETWD_CACHE
, k4
, &str1
);
14088 * Now store a 20 byte string. If the
14089 * total talloced size wasn't accounted for
14090 * and removed in the overwrite, then this
14093 str2
= talloc_zero_size(mem_ctx
, 20);
14094 memcache_add_talloc(cache
, GETWD_CACHE
, k5
, &str2
);
14096 ptr3
= memcache_lookup_talloc(cache
, GETWD_CACHE
, k4
);
14097 if (ptr3
== NULL
) {
14098 printf("Did not find k4, should not have been purged\n");
14102 TALLOC_FREE(cache
);
14103 TALLOC_FREE(mem_ctx
);
14105 mem_ctx
= talloc_init("foo");
14106 if (mem_ctx
== NULL
) {
14110 cache
= memcache_init(NULL
, 0);
14111 if (cache
== NULL
) {
14115 str1
= talloc_strdup(mem_ctx
, "string1");
14116 if (str1
== NULL
) {
14119 str2
= talloc_strdup(mem_ctx
, "string2");
14120 if (str2
== NULL
) {
14123 memcache_add_talloc(cache
, SINGLETON_CACHE_TALLOC
,
14124 data_blob_string_const("torture"), &str1
);
14125 size1
= talloc_total_size(cache
);
14127 memcache_add_talloc(cache
, SINGLETON_CACHE_TALLOC
,
14128 data_blob_string_const("torture"), &str2
);
14129 size2
= talloc_total_size(cache
);
14131 printf("size1=%d, size2=%d\n", (int)size1
, (int)size2
);
14133 if (size2
> size1
) {
14134 printf("memcache leaks memory!\n");
14140 TALLOC_FREE(cache
);
14144 static void wbclient_done(struct tevent_req
*req
)
14147 struct winbindd_response
*wb_resp
;
14148 int *i
= (int *)tevent_req_callback_data_void(req
);
14150 wbc_err
= wb_trans_recv(req
, req
, &wb_resp
);
14153 d_printf("wb_trans_recv %d returned %s\n", *i
, wbcErrorString(wbc_err
));
14156 static bool run_wbclient_multi_ping(int dummy
)
14158 struct tevent_context
*ev
;
14159 struct wb_context
**wb_ctx
;
14160 struct winbindd_request wb_req
;
14161 bool result
= false;
14164 BlockSignals(True
, SIGPIPE
);
14166 ev
= tevent_context_init(talloc_tos());
14171 wb_ctx
= talloc_array(ev
, struct wb_context
*, torture_nprocs
);
14172 if (wb_ctx
== NULL
) {
14176 ZERO_STRUCT(wb_req
);
14177 wb_req
.cmd
= WINBINDD_PING
;
14179 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs
, (int)torture_numops
);
14181 for (i
=0; i
<torture_nprocs
; i
++) {
14182 wb_ctx
[i
] = wb_context_init(ev
, NULL
);
14183 if (wb_ctx
[i
] == NULL
) {
14186 for (j
=0; j
<torture_numops
; j
++) {
14187 struct tevent_req
*req
;
14188 req
= wb_trans_send(ev
, ev
, wb_ctx
[i
],
14189 (j
% 2) == 0, &wb_req
);
14193 tevent_req_set_callback(req
, wbclient_done
, &i
);
14199 while (i
< torture_nprocs
* torture_numops
) {
14200 tevent_loop_once(ev
);
14209 static bool dbtrans_inc(struct db_context
*db
)
14211 struct db_record
*rec
;
14217 rec
= dbwrap_fetch_locked(db
, db
, string_term_tdb_data("transtest"));
14219 printf(__location__
"fetch_lock failed\n");
14223 value
= dbwrap_record_get_value(rec
);
14225 if (value
.dsize
!= sizeof(uint32_t)) {
14226 printf(__location__
"value.dsize = %d\n",
14231 memcpy(&val
, value
.dptr
, sizeof(val
));
14234 status
= dbwrap_record_store(
14235 rec
, make_tdb_data((uint8_t *)&val
, sizeof(val
)), 0);
14236 if (!NT_STATUS_IS_OK(status
)) {
14237 printf(__location__
"store failed: %s\n",
14238 nt_errstr(status
));
14248 static bool run_local_dbtrans(int dummy
)
14250 struct db_context
*db
;
14251 struct db_record
*rec
;
14257 db
= db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT
,
14258 O_RDWR
|O_CREAT
, 0600, DBWRAP_LOCK_ORDER_1
,
14261 printf("Could not open transtest.db\n");
14265 res
= dbwrap_transaction_start(db
);
14267 printf(__location__
"transaction_start failed\n");
14271 rec
= dbwrap_fetch_locked(db
, db
, string_term_tdb_data("transtest"));
14273 printf(__location__
"fetch_lock failed\n");
14277 value
= dbwrap_record_get_value(rec
);
14279 if (value
.dptr
== NULL
) {
14281 status
= dbwrap_record_store(
14282 rec
, make_tdb_data((uint8_t *)&initial
,
14285 if (!NT_STATUS_IS_OK(status
)) {
14286 printf(__location__
"store returned %s\n",
14287 nt_errstr(status
));
14294 res
= dbwrap_transaction_commit(db
);
14296 printf(__location__
"transaction_commit failed\n");
14301 uint32_t val
, val2
;
14304 res
= dbwrap_transaction_start(db
);
14306 printf(__location__
"transaction_start failed\n");
14310 status
= dbwrap_fetch_uint32_bystring(db
, "transtest", &val
);
14311 if (!NT_STATUS_IS_OK(status
)) {
14312 printf(__location__
"dbwrap_fetch_uint32 failed: %s\n",
14313 nt_errstr(status
));
14317 for (i
=0; i
<10; i
++) {
14318 if (!dbtrans_inc(db
)) {
14323 status
= dbwrap_fetch_uint32_bystring(db
, "transtest", &val2
);
14324 if (!NT_STATUS_IS_OK(status
)) {
14325 printf(__location__
"dbwrap_fetch_uint32 failed: %s\n",
14326 nt_errstr(status
));
14330 if (val2
!= val
+ 10) {
14331 printf(__location__
"val=%d, val2=%d\n",
14332 (int)val
, (int)val2
);
14336 printf("val2=%d\r", val2
);
14338 res
= dbwrap_transaction_commit(db
);
14340 printf(__location__
"transaction_commit failed\n");
14350 * Just a dummy test to be run under a debugger. There's no real way
14351 * to inspect the tevent_poll specific function from outside of
14355 static bool run_local_tevent_poll(int dummy
)
14357 struct tevent_context
*ev
;
14358 struct tevent_fd
*fd1
, *fd2
;
14359 bool result
= false;
14361 ev
= tevent_context_init_byname(NULL
, "poll");
14363 d_fprintf(stderr
, "tevent_context_init_byname failed\n");
14367 fd1
= tevent_add_fd(ev
, ev
, 2, 0, NULL
, NULL
);
14369 d_fprintf(stderr
, "tevent_add_fd failed\n");
14372 fd2
= tevent_add_fd(ev
, ev
, 3, 0, NULL
, NULL
);
14374 d_fprintf(stderr
, "tevent_add_fd failed\n");
14379 fd2
= tevent_add_fd(ev
, ev
, 1, 0, NULL
, NULL
);
14381 d_fprintf(stderr
, "tevent_add_fd failed\n");
14391 static bool run_local_hex_encode_buf(int dummy
)
14397 for (i
=0; i
<sizeof(src
); i
++) {
14400 hex_encode_buf(buf
, src
, sizeof(src
));
14401 if (strcmp(buf
, "0001020304050607") != 0) {
14404 hex_encode_buf(buf
, NULL
, 0);
14405 if (buf
[0] != '\0') {
14411 static const char *remove_duplicate_addrs2_test_strings_vector
[] = {
14433 "1001:1111:1111:1000:0:1111:1111:1111",
14442 static const char *remove_duplicate_addrs2_test_strings_result
[] = {
14456 "1001:1111:1111:1000:0:1111:1111:1111"
14459 static bool run_local_remove_duplicate_addrs2(int dummy
)
14461 struct samba_sockaddr test_vector
[28];
14464 /* Construct the sockaddr_storage test vector. */
14465 for (i
= 0; i
< 28; i
++) {
14466 struct addrinfo hints
;
14467 struct addrinfo
*res
= NULL
;
14470 memset(&hints
, '\0', sizeof(hints
));
14471 hints
.ai_flags
= AI_NUMERICHOST
;
14472 ret
= getaddrinfo(remove_duplicate_addrs2_test_strings_vector
[i
],
14477 fprintf(stderr
, "getaddrinfo failed on [%s]\n",
14478 remove_duplicate_addrs2_test_strings_vector
[i
]);
14481 memset(&test_vector
[i
], '\0', sizeof(test_vector
[i
]));
14482 memcpy(&test_vector
[i
].u
.ss
,
14488 count
= remove_duplicate_addrs2(test_vector
, i
);
14491 fprintf(stderr
, "count wrong (%zu) should be 14\n",
14496 for (i
= 0; i
< count
; i
++) {
14497 char addr
[INET6_ADDRSTRLEN
];
14499 print_sockaddr(addr
, sizeof(addr
), &test_vector
[i
].u
.ss
);
14501 if (strcmp(addr
, remove_duplicate_addrs2_test_strings_result
[i
]) != 0) {
14502 fprintf(stderr
, "mismatch on [%zu] [%s] [%s]\n",
14505 remove_duplicate_addrs2_test_strings_result
[i
]);
14510 printf("run_local_remove_duplicate_addrs2: success\n");
14514 static bool run_local_tdb_opener(int dummy
)
14520 t
= tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST
,
14521 O_RDWR
|O_CREAT
, 0755);
14523 perror("tdb_open failed");
14534 static bool run_local_tdb_writer(int dummy
)
14540 t
= tdb_open("test.tdb", 1000, 0, O_RDWR
|O_CREAT
, 0755);
14542 perror("tdb_open failed");
14546 val
.dptr
= (uint8_t *)&v
;
14547 val
.dsize
= sizeof(v
);
14553 ret
= tdb_store(t
, val
, val
, 0);
14555 printf("%s\n", tdb_errorstr(t
));
14560 data
= tdb_fetch(t
, val
);
14561 if (data
.dptr
!= NULL
) {
14562 SAFE_FREE(data
.dptr
);
14568 static bool run_local_canonicalize_path(int dummy
)
14570 const char *src
[] = {
14577 ".././././../../../boo",
14589 "/foo/bar/../baz/",
14590 "////////////////",
14591 "/////////./././././.",
14592 "/./.././../.boo/../baz",
14593 "/a/component/path",
14594 "/a/component/path/",
14595 "/a/component/path/..",
14596 "/a/component/../path/",
14597 "///a/./././///component/../////path/",
14600 const char *dst
[] = {
14623 "/a/component/path",
14624 "/a/component/path",
14632 for (i
= 0; src
[i
] != NULL
; i
++) {
14633 char *d
= canonicalize_absolute_path(talloc_tos(), src
[i
]);
14635 perror("talloc fail\n");
14638 if (strcmp(d
, dst
[i
]) != 0) {
14640 "canonicalize mismatch %s -> %s != %s",
14641 src
[i
], d
, dst
[i
]);
14649 static bool run_ign_bad_negprot(int dummy
)
14651 struct tevent_context
*ev
;
14652 struct tevent_req
*req
;
14653 struct smbXcli_conn
*conn
;
14654 struct sockaddr_storage ss
;
14659 printf("starting ignore bad negprot\n");
14661 ok
= resolve_name(host
, &ss
, 0x20, true);
14663 d_fprintf(stderr
, "Could not resolve name %s\n", host
);
14667 status
= open_socket_out(&ss
, 445, 10000, &fd
);
14668 if (!NT_STATUS_IS_OK(status
)) {
14669 d_fprintf(stderr
, "open_socket_out failed: %s\n",
14670 nt_errstr(status
));
14674 conn
= smbXcli_conn_create(talloc_tos(), fd
, host
, SMB_SIGNING_OFF
, 0,
14676 if (conn
== NULL
) {
14677 d_fprintf(stderr
, "smbXcli_conn_create failed\n");
14681 status
= smbXcli_negprot(conn
, 0, PROTOCOL_CORE
, PROTOCOL_CORE
);
14682 if (NT_STATUS_IS_OK(status
)) {
14683 d_fprintf(stderr
, "smbXcli_negprot succeeded!\n");
14687 ev
= samba_tevent_context_init(talloc_tos());
14689 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
14693 req
= smb1cli_session_setup_nt1_send(
14694 ev
, ev
, conn
, 0, getpid(), NULL
, 65503, 2, 1, 0, "", "",
14695 data_blob_null
, data_blob_null
, 0x40,
14696 "Windows 2000 2195", "Windows 2000 5.0");
14698 d_fprintf(stderr
, "smb1cli_session_setup_nt1_send failed\n");
14702 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
14704 d_fprintf(stderr
, "tevent_req_poll failed\n");
14708 status
= smb1cli_session_setup_nt1_recv(req
, NULL
, NULL
, NULL
, NULL
,
14710 if (!NT_STATUS_EQUAL(status
, NT_STATUS_CONNECTION_RESET
)) {
14711 d_fprintf(stderr
, "smb1cli_session_setup_nt1_recv returned "
14712 "%s, expected NT_STATUS_CONNECTION_RESET\n",
14713 nt_errstr(status
));
14719 printf("starting ignore bad negprot\n");
14724 static double create_procs(bool (*fn
)(int), bool *result
)
14727 volatile pid_t
*child_status
;
14728 volatile bool *child_status_out
;
14731 struct timeval start
;
14735 child_status
= (volatile pid_t
*)anonymous_shared_allocate(sizeof(pid_t
)*torture_nprocs
);
14736 if (!child_status
) {
14737 printf("Failed to setup shared memory\n");
14741 child_status_out
= (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs
);
14742 if (!child_status_out
) {
14743 printf("Failed to setup result status shared memory\n");
14747 for (i
= 0; i
< torture_nprocs
; i
++) {
14748 child_status
[i
] = 0;
14749 child_status_out
[i
] = True
;
14752 start
= timeval_current();
14754 for (i
=0;i
<torture_nprocs
;i
++) {
14757 pid_t mypid
= getpid();
14758 sys_srandom(((int)mypid
) ^ ((int)time(NULL
)));
14760 slprintf(myname
,sizeof(myname
),"CLIENT%d", i
);
14763 if (torture_open_connection(¤t_cli
, i
)) break;
14764 if (tries
-- == 0) {
14765 printf("pid %d failed to start\n", (int)getpid());
14771 child_status
[i
] = getpid();
14773 while (child_status
[i
] && timeval_elapsed(&start
) < 5) smb_msleep(2);
14775 child_status_out
[i
] = fn(i
);
14782 for (i
=0;i
<torture_nprocs
;i
++) {
14783 if (child_status
[i
]) synccount
++;
14785 if (synccount
== torture_nprocs
) break;
14787 } while (timeval_elapsed(&start
) < 30);
14789 if (synccount
!= torture_nprocs
) {
14790 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs
, synccount
);
14792 return timeval_elapsed(&start
);
14795 /* start the client load */
14796 start
= timeval_current();
14798 for (i
=0;i
<torture_nprocs
;i
++) {
14799 child_status
[i
] = 0;
14802 printf("%d clients started\n", torture_nprocs
);
14804 for (i
=0;i
<torture_nprocs
;i
++) {
14805 while (waitpid(0, &status
, 0) == -1 && errno
== EINTR
) /* noop */ ;
14810 for (i
=0;i
<torture_nprocs
;i
++) {
14811 if (!child_status_out
[i
]) {
14815 return timeval_elapsed(&start
);
14818 #define FLAG_MULTIPROC 1
14824 } torture_ops
[] = {
14827 .fn
= run_fdpasstest
,
14831 .fn
= run_locktest1
,
14835 .fn
= run_locktest2
,
14839 .fn
= run_locktest3
,
14843 .fn
= run_locktest4
,
14847 .fn
= run_locktest5
,
14851 .fn
= run_locktest6
,
14855 .fn
= run_locktest7
,
14859 .fn
= run_locktest8
,
14863 .fn
= run_locktest9a
,
14867 .fn
= run_locktest9b
,
14871 .fn
= run_locktest10
,
14875 .fn
= run_locktest11
,
14879 .fn
= run_locktest12
,
14883 .fn
= run_locktest13
,
14887 .fn
= run_unlinktest
,
14891 .fn
= run_browsetest
,
14895 .fn
= run_attrtest
,
14899 .fn
= run_trans2test
,
14903 .fn
= run_maxfidtest
,
14904 .flags
= FLAG_MULTIPROC
,
14909 .flags
= FLAG_MULTIPROC
,
14912 .name
= "RANDOMIPC",
14913 .fn
= run_randomipc
,
14916 .name
= "NEGNOWAIT",
14917 .fn
= run_negprot_nowait
,
14939 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14951 .fn
= run_dirtest1
,
14954 .name
= "DIR-CREATETIME",
14955 .fn
= run_dir_createtime
,
14959 .fn
= torture_denytest1
,
14963 .fn
= torture_denytest2
,
14967 .fn
= run_tcon_test
,
14971 .fn
= run_tcon_devtype_test
,
14975 .fn
= run_readwritetest
,
14979 .fn
= run_readwritemulti
,
14980 .flags
= FLAG_MULTIPROC
14984 .fn
= run_readwritelarge
,
14987 .name
= "RW-SIGNING",
14988 .fn
= run_readwritelarge_signtest
,
14992 .fn
= run_opentest
,
14996 .fn
= run_simple_posix_open_test
,
14999 .name
= "POSIX-APPEND",
15000 .fn
= run_posix_append
,
15003 .name
= "POSIX-SYMLINK-ACL",
15004 .fn
= run_acl_symlink_test
,
15007 .name
= "POSIX-SYMLINK-EA",
15008 .fn
= run_ea_symlink_test
,
15011 .name
= "POSIX-STREAM-DELETE",
15012 .fn
= run_posix_stream_delete
,
15015 .name
= "POSIX-OFD-LOCK",
15016 .fn
= run_posix_ofd_lock_test
,
15019 .name
= "POSIX-BLOCKING-LOCK",
15020 .fn
= run_posix_blocking_lock
,
15023 .name
= "POSIX-MKDIR",
15024 .fn
= run_posix_mkdir_test
,
15027 .name
= "POSIX-ACL-OPLOCK",
15028 .fn
= run_posix_acl_oplock_test
,
15031 .name
= "POSIX-ACL-SHAREROOT",
15032 .fn
= run_posix_acl_shareroot_test
,
15035 .name
= "POSIX-LS-WILDCARD",
15036 .fn
= run_posix_ls_wildcard_test
,
15039 .name
= "POSIX-LS-SINGLE",
15040 .fn
= run_posix_ls_single_test
,
15043 .name
= "POSIX-READLINK",
15044 .fn
= run_posix_readlink_test
,
15047 .name
= "POSIX-STAT",
15048 .fn
= run_posix_stat_test
,
15051 .name
= "POSIX-SYMLINK-PARENT",
15052 .fn
= run_posix_symlink_parent_test
,
15055 .name
= "POSIX-SYMLINK-CHMOD",
15056 .fn
= run_posix_symlink_chmod_test
,
15059 .name
= "POSIX-SYMLINK-RENAME",
15060 .fn
= run_posix_symlink_rename_test
,
15063 .name
= "POSIX-DIR-DEFAULT-ACL",
15064 .fn
= run_posix_dir_default_acl_test
,
15067 .name
= "POSIX-SYMLINK-GETPATHINFO",
15068 .fn
= run_posix_symlink_getpathinfo_test
,
15071 .name
= "POSIX-SYMLINK-SETPATHINFO",
15072 .fn
= run_posix_symlink_setpathinfo_test
,
15075 .name
= "WINDOWS-BAD-SYMLINK",
15076 .fn
= run_symlink_open_test
,
15079 .name
= "SMB1-WILD-MANGLE-UNLINK",
15080 .fn
= run_smb1_wild_mangle_unlink_test
,
15083 .name
= "SMB1-WILD-MANGLE-RENAME",
15084 .fn
= run_smb1_wild_mangle_rename_test
,
15087 .name
= "CASE-INSENSITIVE-CREATE",
15088 .fn
= run_case_insensitive_create
,
15091 .name
= "ASYNC-ECHO",
15092 .fn
= run_async_echo
,
15095 .name
= "UID-REGRESSION-TEST",
15096 .fn
= run_uid_regression_test
,
15099 .name
= "SHORTNAME-TEST",
15100 .fn
= run_shortname_test
,
15103 .name
= "ADDRCHANGE",
15104 .fn
= run_addrchange
,
15108 .name
= "OPENATTR",
15109 .fn
= run_openattrtest
,
15121 .name
= "RENAME-ACCESS",
15122 .fn
= run_rename_access
,
15125 .name
= "OWNER-RIGHTS",
15126 .fn
= run_owner_rights
,
15130 .fn
= run_deletetest
,
15133 .name
= "DELETE-STREAM",
15134 .fn
= run_delete_stream
,
15137 .name
= "DELETE-PRINT",
15138 .fn
= run_delete_print_test
,
15141 .name
= "DELETE-LN",
15142 .fn
= run_deletetest_ln
,
15145 .name
= "PROPERTIES",
15146 .fn
= run_properties
,
15150 .fn
= torture_mangle
,
15157 .name
= "MANGLE-ILLEGAL",
15158 .fn
= run_mangle_illegal
,
15165 .name
= "TRANS2SCAN",
15166 .fn
= torture_trans2_scan
,
15169 .name
= "NTTRANSSCAN",
15170 .fn
= torture_nttrans_scan
,
15174 .fn
= torture_utable
,
15177 .name
= "CASETABLE",
15178 .fn
= torture_casetable
,
15181 .name
= "ERRMAPEXTRACT",
15182 .fn
= run_error_map_extract
,
15185 .name
= "PIPE_NUMBER",
15186 .fn
= run_pipe_number
,
15190 .fn
= run_tcon2_test
,
15194 .fn
= torture_ioctl_test
,
15198 .fn
= torture_chkpath_test
,
15202 .fn
= run_fdsesstest
,
15209 .name
= "SESSSETUP_BENCH",
15210 .fn
= run_sesssetup_bench
,
15225 .name
= "WINDOWS-WRITE",
15226 .fn
= run_windows_write
,
15229 .name
= "LARGE_READX",
15230 .fn
= run_large_readx
,
15233 .name
= "MSDFS-ATTRIBUTE",
15234 .fn
= run_msdfs_attribute
,
15237 .name
= "NTTRANS-CREATE",
15238 .fn
= run_nttrans_create
,
15241 .name
= "NTTRANS-FSCTL",
15242 .fn
= run_nttrans_fsctl
,
15245 .name
= "CLI_ECHO",
15246 .fn
= run_cli_echo
,
15249 .name
= "CLI_SPLICE",
15250 .fn
= run_cli_splice
,
15257 .name
= "STREAMERROR",
15258 .fn
= run_streamerror
,
15261 .name
= "NOTIFY-BENCH",
15262 .fn
= run_notify_bench
,
15265 .name
= "NOTIFY-BENCH2",
15266 .fn
= run_notify_bench2
,
15269 .name
= "NOTIFY-BENCH3",
15270 .fn
= run_notify_bench3
,
15273 .name
= "BAD-NBT-SESSION",
15274 .fn
= run_bad_nbt_session
,
15277 .name
= "IGN-BAD-NEGPROT",
15278 .fn
= run_ign_bad_negprot
,
15281 .name
= "SMB-ANY-CONNECT",
15282 .fn
= run_smb_any_connect
,
15285 .name
= "NOTIFY-ONLINE",
15286 .fn
= run_notify_online
,
15289 .name
= "SMB2-BASIC",
15290 .fn
= run_smb2_basic
,
15293 .name
= "SMB2-NEGPROT",
15294 .fn
= run_smb2_negprot
,
15297 .name
= "SMB2-ANONYMOUS",
15298 .fn
= run_smb2_anonymous
,
15301 .name
= "SMB2-SESSION-RECONNECT",
15302 .fn
= run_smb2_session_reconnect
,
15305 .name
= "SMB2-TCON-DEPENDENCE",
15306 .fn
= run_smb2_tcon_dependence
,
15309 .name
= "SMB2-MULTI-CHANNEL",
15310 .fn
= run_smb2_multi_channel
,
15313 .name
= "SMB2-SESSION-REAUTH",
15314 .fn
= run_smb2_session_reauth
,
15317 .name
= "SMB2-FTRUNCATE",
15318 .fn
= run_smb2_ftruncate
,
15321 .name
= "SMB2-DIR-FSYNC",
15322 .fn
= run_smb2_dir_fsync
,
15325 .name
= "SMB2-PATH-SLASH",
15326 .fn
= run_smb2_path_slash
,
15329 .name
= "SMB1-SYSTEM-SECURITY",
15330 .fn
= run_smb1_system_security
,
15333 .name
= "SMB2-SACL",
15334 .fn
= run_smb2_sacl
,
15337 .name
= "SMB2-QUOTA1",
15338 .fn
= run_smb2_quota1
,
15341 .name
= "SMB2-STREAM-ACL",
15342 .fn
= run_smb2_stream_acl
,
15345 .name
= "SMB2-LIST-DIR-ASYNC",
15346 .fn
= run_list_dir_async_test
,
15349 .name
= "SMB2-DEL-ON-CLOSE-NONEMPTY",
15350 .fn
= run_delete_on_close_non_empty
,
15353 .name
= "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15354 .fn
= run_delete_on_close_nonwrite_delete_yes_test
,
15357 .name
= "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15358 .fn
= run_delete_on_close_nonwrite_delete_no_test
,
15361 .name
= "SMB2-DFS-PATHS",
15362 .fn
= run_smb2_dfs_paths
,
15365 .name
= "SMB2-NON-DFS-SHARE",
15366 .fn
= run_smb2_non_dfs_share
,
15369 .name
= "SMB2-DFS-SHARE-NON-DFS-PATH",
15370 .fn
= run_smb2_dfs_share_non_dfs_path
,
15373 .name
= "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15374 .fn
= run_smb2_dfs_filename_leading_backslash
,
15377 .name
= "SMB1-DFS-PATHS",
15378 .fn
= run_smb1_dfs_paths
,
15381 .name
= "SMB1-DFS-SEARCH-PATHS",
15382 .fn
= run_smb1_dfs_search_paths
,
15385 .name
= "SMB1-DFS-OPERATIONS",
15386 .fn
= run_smb1_dfs_operations
,
15389 .name
= "CLEANUP1",
15390 .fn
= run_cleanup1
,
15393 .name
= "CLEANUP2",
15394 .fn
= run_cleanup2
,
15397 .name
= "CLEANUP4",
15398 .fn
= run_cleanup4
,
15401 .name
= "OPLOCK-CANCEL",
15402 .fn
= run_oplock_cancel
,
15409 .name
= "LOCAL-SUBSTITUTE",
15410 .fn
= run_local_substitute
,
15413 .name
= "LOCAL-GENCACHE",
15414 .fn
= run_local_gencache
,
15417 .name
= "LOCAL-DBWRAP-WATCH1",
15418 .fn
= run_dbwrap_watch1
,
15421 .name
= "LOCAL-DBWRAP-WATCH2",
15422 .fn
= run_dbwrap_watch2
,
15425 .name
= "LOCAL-DBWRAP-WATCH3",
15426 .fn
= run_dbwrap_watch3
,
15429 .name
= "LOCAL-DBWRAP-WATCH4",
15430 .fn
= run_dbwrap_watch4
,
15433 .name
= "LOCAL-DBWRAP-DO-LOCKED1",
15434 .fn
= run_dbwrap_do_locked1
,
15437 .name
= "LOCAL-MESSAGING-READ1",
15438 .fn
= run_messaging_read1
,
15441 .name
= "LOCAL-MESSAGING-READ2",
15442 .fn
= run_messaging_read2
,
15445 .name
= "LOCAL-MESSAGING-READ3",
15446 .fn
= run_messaging_read3
,
15449 .name
= "LOCAL-MESSAGING-READ4",
15450 .fn
= run_messaging_read4
,
15453 .name
= "LOCAL-MESSAGING-FDPASS1",
15454 .fn
= run_messaging_fdpass1
,
15457 .name
= "LOCAL-MESSAGING-FDPASS2",
15458 .fn
= run_messaging_fdpass2
,
15461 .name
= "LOCAL-MESSAGING-FDPASS2a",
15462 .fn
= run_messaging_fdpass2a
,
15465 .name
= "LOCAL-MESSAGING-FDPASS2b",
15466 .fn
= run_messaging_fdpass2b
,
15469 .name
= "LOCAL-MESSAGING-SEND-ALL",
15470 .fn
= run_messaging_send_all
,
15473 .name
= "LOCAL-BASE64",
15474 .fn
= run_local_base64
,
15477 .name
= "LOCAL-RBTREE",
15478 .fn
= run_local_rbtree
,
15481 .name
= "LOCAL-MEMCACHE",
15482 .fn
= run_local_memcache
,
15485 .name
= "LOCAL-STREAM-NAME",
15486 .fn
= run_local_stream_name
,
15489 .name
= "LOCAL-STR-MATCH-MSWILD",
15490 .fn
= run_str_match_mswild
,
15493 .name
= "LOCAL-STR-MATCH-REGEX-SUB1",
15494 .fn
= run_str_match_regex_sub1
,
15497 .name
= "WBCLIENT-MULTI-PING",
15498 .fn
= run_wbclient_multi_ping
,
15501 .name
= "LOCAL-string_to_sid",
15502 .fn
= run_local_string_to_sid
,
15505 .name
= "LOCAL-sid_to_string",
15506 .fn
= run_local_sid_to_string
,
15509 .name
= "LOCAL-binary_to_sid",
15510 .fn
= run_local_binary_to_sid
,
15513 .name
= "LOCAL-DBTRANS",
15514 .fn
= run_local_dbtrans
,
15517 .name
= "LOCAL-TEVENT-POLL",
15518 .fn
= run_local_tevent_poll
,
15521 .name
= "LOCAL-CONVERT-STRING",
15522 .fn
= run_local_convert_string
,
15525 .name
= "LOCAL-CONV-AUTH-INFO",
15526 .fn
= run_local_conv_auth_info
,
15529 .name
= "LOCAL-hex_encode_buf",
15530 .fn
= run_local_hex_encode_buf
,
15533 .name
= "LOCAL-IDMAP-TDB-COMMON",
15534 .fn
= run_idmap_tdb_common_test
,
15537 .name
= "LOCAL-remove_duplicate_addrs2",
15538 .fn
= run_local_remove_duplicate_addrs2
,
15541 .name
= "local-tdb-opener",
15542 .fn
= run_local_tdb_opener
,
15545 .name
= "local-tdb-writer",
15546 .fn
= run_local_tdb_writer
,
15549 .name
= "LOCAL-DBWRAP-CTDB1",
15550 .fn
= run_local_dbwrap_ctdb1
,
15553 .name
= "LOCAL-BENCH-PTHREADPOOL",
15554 .fn
= run_bench_pthreadpool
,
15557 .name
= "LOCAL-PTHREADPOOL-TEVENT",
15558 .fn
= run_pthreadpool_tevent
,
15561 .name
= "LOCAL-G-LOCK1",
15565 .name
= "LOCAL-G-LOCK2",
15569 .name
= "LOCAL-G-LOCK3",
15573 .name
= "LOCAL-G-LOCK4",
15577 .name
= "LOCAL-G-LOCK4A",
15578 .fn
= run_g_lock4a
,
15581 .name
= "LOCAL-G-LOCK5",
15585 .name
= "LOCAL-G-LOCK6",
15589 .name
= "LOCAL-G-LOCK7",
15593 .name
= "LOCAL-G-LOCK8",
15597 .name
= "LOCAL-G-LOCK-PING-PONG",
15598 .fn
= run_g_lock_ping_pong
,
15601 .name
= "LOCAL-CANONICALIZE-PATH",
15602 .fn
= run_local_canonicalize_path
,
15605 .name
= "LOCAL-NAMEMAP-CACHE1",
15606 .fn
= run_local_namemap_cache1
,
15609 .name
= "LOCAL-IDMAP-CACHE1",
15610 .fn
= run_local_idmap_cache1
,
15613 .name
= "qpathinfo-bufsize",
15614 .fn
= run_qpathinfo_bufsize
,
15617 .name
= "hide-new-files-timeout",
15618 .fn
= run_hidenewfiles
,
15621 .name
= "hide-new-files-timeout-showdirs",
15622 .fn
= run_hidenewfiles_showdirs
,
15624 #ifdef CLUSTER_SUPPORT
15626 .name
= "ctdbd-conn1",
15627 .fn
= run_ctdbd_conn1
,
15631 .name
= "readdir-timestamp",
15632 .fn
= run_readdir_timestamp
,
15635 .name
= "rpc-scale",
15636 .fn
= run_rpc_scale
,
15643 /****************************************************************************
15644 run a specified test or "ALL"
15645 ****************************************************************************/
15646 static bool run_test(const char *name
)
15649 bool result
= True
;
15650 bool found
= False
;
15653 if (strequal(name
,"ALL")) {
15654 for (i
=0;torture_ops
[i
].name
;i
++) {
15655 run_test(torture_ops
[i
].name
);
15660 for (i
=0;torture_ops
[i
].name
;i
++) {
15661 fstr_sprintf(randomfname
, "\\XX%x",
15662 (unsigned)random());
15664 if (strequal(name
, torture_ops
[i
].name
)) {
15666 printf("Running %s\n", name
);
15667 if (torture_ops
[i
].flags
& FLAG_MULTIPROC
) {
15668 t
= create_procs(torture_ops
[i
].fn
, &result
);
15671 printf("TEST %s FAILED!\n", name
);
15674 struct timeval start
;
15675 start
= timeval_current();
15676 if (!torture_ops
[i
].fn(0)) {
15678 printf("TEST %s FAILED!\n", name
);
15680 t
= timeval_elapsed(&start
);
15682 printf("%s took %g secs\n\n", name
, t
);
15687 printf("Did not find a test named %s\n", name
);
15695 static void usage(void)
15699 printf("WARNING samba4 test suite is much more complete nowadays.\n");
15700 printf("Please use samba4 torture.\n\n");
15702 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15704 printf("\t-d debuglevel\n");
15705 printf("\t-U user%%pass\n");
15706 printf("\t-k use kerberos\n");
15707 printf("\t-N numprocs\n");
15708 printf("\t-n my_netbios_name\n");
15709 printf("\t-W workgroup\n");
15710 printf("\t-o num_operations\n");
15711 printf("\t-O socket_options\n");
15712 printf("\t-m maximum protocol\n");
15713 printf("\t-L use oplocks\n");
15714 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
15715 printf("\t-A showall\n");
15716 printf("\t-p port\n");
15717 printf("\t-s seed\n");
15718 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
15719 printf("\t-f filename filename to test\n");
15720 printf("\t-e encrypt\n");
15723 printf("tests are:");
15724 for (i
=0;torture_ops
[i
].name
;i
++) {
15725 printf(" %s", torture_ops
[i
].name
);
15729 printf("default test is ALL\n");
15734 /****************************************************************************
15736 ****************************************************************************/
15737 int main(int argc
,char *argv
[])
15743 bool correct
= True
;
15744 TALLOC_CTX
*frame
= talloc_stackframe();
15745 int seed
= time(NULL
);
15747 #ifdef HAVE_SETBUFFER
15748 setbuffer(stdout
, NULL
, 0);
15751 setup_logging("smbtorture", DEBUG_STDOUT
);
15756 if (is_default_dyn_CONFIGFILE()) {
15757 if(getenv("SMB_CONF_PATH")) {
15758 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15761 lp_load_global(get_dyn_CONFIGFILE());
15768 for(p
= argv
[1]; *p
; p
++)
15772 if (strncmp(argv
[1], "//", 2)) {
15776 fstrcpy(host
, &argv
[1][2]);
15777 p
= strchr_m(&host
[2],'/');
15782 fstrcpy(share
, p
+1);
15784 fstrcpy(myname
, get_myname(talloc_tos()));
15786 fprintf(stderr
, "Failed to get my hostname.\n");
15790 if (*username
== 0 && getenv("LOGNAME")) {
15791 fstrcpy(username
,getenv("LOGNAME"));
15797 fstrcpy(workgroup
, lp_workgroup());
15799 while ((opt
= getopt(argc
, argv
, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15803 port_to_use
= atoi(optarg
);
15806 seed
= atoi(optarg
);
15809 fstrcpy(workgroup
,optarg
);
15812 lp_set_cmdline("client max protocol", optarg
);
15815 torture_nprocs
= atoi(optarg
);
15818 torture_numops
= atoi(optarg
);
15821 lp_set_cmdline("log level", optarg
);
15827 use_oplocks
= True
;
15830 local_path
= optarg
;
15833 torture_showall
= True
;
15836 fstrcpy(myname
, optarg
);
15839 client_txt
= optarg
;
15846 use_kerberos
= True
;
15848 d_printf("No kerberos support compiled in\n");
15854 fstrcpy(username
,optarg
);
15855 p
= strchr_m(username
,'%');
15858 fstrcpy(password
, p
+1);
15863 fstrcpy(multishare_conn_fname
, optarg
);
15864 use_multishare_conn
= True
;
15867 torture_blocksize
= atoi(optarg
);
15870 test_filename
= SMB_STRDUP(optarg
);
15873 printf("Unknown option %c (%d)\n", (char)opt
, opt
);
15878 d_printf("using seed %d\n", seed
);
15882 if(use_kerberos
&& !gotuser
) gotpass
= True
;
15885 char pwd
[256] = {0};
15888 rc
= samba_getpass("Password:", pwd
, sizeof(pwd
), false, false);
15890 fstrcpy(password
, pwd
);
15895 printf("host=%s share=%s user=%s myname=%s\n",
15896 host
, share
, username
, myname
);
15898 torture_creds
= cli_session_creds_init(frame
,
15904 false, /* fallback_after_kerberos */
15905 false, /* use_ccache */
15906 false); /* password_is_nt_hash */
15907 if (torture_creds
== NULL
) {
15908 d_printf("cli_session_creds_init() failed.\n");
15912 if (argc
== optind
) {
15913 correct
= run_test("ALL");
15915 for (i
=optind
;i
<argc
;i
++) {
15916 if (!run_test(argv
[i
])) {
15922 TALLOC_FREE(frame
);