2 Unix SMB/CIFS implementation.
3 Copyright (C) Ralph Boehme 2020
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "torture/proto.h"
21 #include "libcli/security/security.h"
22 #include "libsmb/libsmb.h"
23 #include "libsmb/clirap.h"
24 #include "libsmb/proto.h"
25 #include "../libcli/smb/smbXcli_base.h"
29 extern struct cli_credentials
*torture_creds
;
30 extern fstring host
, workgroup
, share
, password
, username
, myname
;
32 struct posix_test_entry
{
38 uint64_t returned_size
;
42 enum client_flavour
{ WINDOWS
, POSIX
};
44 struct posix_test_state
{
45 enum client_flavour flavour
;
46 struct posix_test_entry
*entries
;
49 static NTSTATUS
posix_ls_fn(struct file_info
*finfo
,
53 struct posix_test_state
*state
=
54 (struct posix_test_state
*)_state
;
55 struct posix_test_entry
*e
= state
->entries
;
57 for (; e
->name
!= NULL
; e
++) {
59 if (!strequal(finfo
->name
, e
->expected
)) {
62 if (state
->flavour
== WINDOWS
) {
67 if (attr
!= finfo
->attr
) {
71 e
->returned_size
= finfo
->size
;
78 static void posix_test_entries_reset(struct posix_test_state
*state
)
80 struct posix_test_entry
*e
= state
->entries
;
82 for (; e
->name
!= NULL
; e
++) {
88 static bool posix_test_entry_check(struct posix_test_state
*state
,
91 uint64_t expected_size
)
93 struct posix_test_entry
*e
= state
->entries
;
96 for (; e
->name
!= NULL
; e
++) {
97 if (strequal(name
, e
->name
)) {
102 if (e
->name
== NULL
) {
103 printf("test failed, unknown name: %s\n", name
);
107 if (expected
== result
) {
111 printf("test failed, %s: %s\n",
112 expected
? "missing" : "unexpected",
119 Test non-POSIX vs POSIX ls * of symlinks
121 bool run_posix_ls_wildcard_test(int dummy
)
123 TALLOC_CTX
*frame
= NULL
;
124 struct cli_state
*cli_unix
= NULL
;
125 struct cli_state
*cli_win
= NULL
;
126 uint16_t fnum
= (uint16_t)-1;
128 const char *file
= "file";
129 const char *symlnk_dangling
= "dangling";
130 const char *symlnk_dst_dangling
= "xxxxxxx";
131 const char *symlnk_in_share
= "symlnk_in_share";
132 const char *symlnk_dst_in_share
= file
;
133 const char *symlnk_outside_share
= "symlnk_outside_share";
134 const char *symlnk_dst_outside_share
= "/etc/passwd";
135 struct posix_test_entry entries
[] = {
140 .attr_win
= FILE_ATTRIBUTE_ARCHIVE
,
141 .attr_lin
= FILE_ATTRIBUTE_ARCHIVE
,
143 .name
= symlnk_dangling
,
144 .target
= symlnk_dst_dangling
,
145 .expected
= symlnk_dangling
,
146 .attr_win
= FILE_ATTRIBUTE_INVALID
,
147 .attr_lin
= FILE_ATTRIBUTE_NORMAL
,
149 .name
= symlnk_in_share
,
150 .target
= symlnk_dst_in_share
,
151 .expected
= symlnk_in_share
,
152 .attr_win
= FILE_ATTRIBUTE_ARCHIVE
,
153 .attr_lin
= FILE_ATTRIBUTE_NORMAL
,
155 .name
= symlnk_outside_share
,
156 .target
= symlnk_dst_outside_share
,
157 .expected
= symlnk_outside_share
,
158 .attr_win
= FILE_ATTRIBUTE_INVALID
,
159 .attr_lin
= FILE_ATTRIBUTE_NORMAL
,
164 struct posix_test_state _state
= {
167 struct posix_test_state
*state
= &_state
;
169 bool correct
= false;
171 frame
= talloc_stackframe();
173 printf("Starting POSIX-LS-WILDCARD test\n");
175 if (!torture_open_connection(&cli_unix
, 0)) {
180 if (!torture_open_connection(&cli_win
, 0)) {
185 torture_conn_set_sockopt(cli_unix
);
186 torture_conn_set_sockopt(cli_win
);
188 status
= torture_setup_unix_extensions(cli_unix
);
189 if (!NT_STATUS_IS_OK(status
)) {
194 cli_posix_unlink(cli_unix
, file
);
195 cli_posix_unlink(cli_unix
, symlnk_dangling
);
196 cli_posix_unlink(cli_unix
, symlnk_in_share
);
197 cli_posix_unlink(cli_unix
, symlnk_outside_share
);
199 status
= cli_posix_open(cli_unix
,
204 if (!NT_STATUS_IS_OK(status
)) {
205 printf("cli_posix_open of %s failed error %s\n",
211 status
= cli_close(cli_unix
, fnum
);
212 if (!NT_STATUS_IS_OK(status
)) {
213 printf("cli_close failed %s\n", nt_errstr(status
));
218 for (i
= 0; entries
[i
].name
!= NULL
; i
++) {
219 if (entries
[i
].target
== NULL
) {
222 status
= cli_posix_symlink(cli_unix
,
225 if (!NT_STATUS_IS_OK(status
)) {
226 printf("POSIX symlink of %s failed (%s)\n",
227 symlnk_dangling
, nt_errstr(status
));
232 printf("Doing Windows ls *\n");
233 state
->flavour
= WINDOWS
;
235 status
= cli_list(cli_win
, "*", 0, posix_ls_fn
, state
);
236 if (!NT_STATUS_IS_OK(status
)) {
237 printf("cli_list failed %s\n", nt_errstr(status
));
241 if (!posix_test_entry_check(state
, file
, true, 0)) {
244 if (!posix_test_entry_check(state
, symlnk_dangling
, false, 0)) {
247 if (!posix_test_entry_check(state
, symlnk_outside_share
, false, 0)) {
250 if (!posix_test_entry_check(state
, symlnk_in_share
, true, 0)) {
254 posix_test_entries_reset(state
);
256 printf("Doing POSIX ls *\n");
257 state
->flavour
= POSIX
;
259 status
= cli_list(cli_unix
, "*", 0, posix_ls_fn
, state
);
260 if (!NT_STATUS_IS_OK(status
)) {
261 printf("cli_close failed %s\n", nt_errstr(status
));
265 if (!posix_test_entry_check(state
, file
, true, 0)) {
268 if (!posix_test_entry_check(state
,
271 strlen(symlnk_dst_dangling
)))
275 if (!posix_test_entry_check(state
,
276 symlnk_outside_share
,
278 strlen(symlnk_dst_outside_share
)))
282 if (!posix_test_entry_check(state
,
285 strlen(symlnk_dst_in_share
))) {
289 printf("POSIX-LS-WILDCARD test passed\n");
293 cli_posix_unlink(cli_unix
, file
);
294 cli_posix_unlink(cli_unix
, symlnk_dangling
);
295 cli_posix_unlink(cli_unix
, symlnk_in_share
);
296 cli_posix_unlink(cli_unix
, symlnk_outside_share
);
298 if (!torture_close_connection(cli_unix
)) {
301 if (!torture_close_connection(cli_win
)) {
310 Test non-POSIX vs POSIX ls single of symlinks
312 bool run_posix_ls_single_test(int dummy
)
314 TALLOC_CTX
*frame
= NULL
;
315 struct cli_state
*cli_unix
= NULL
;
316 struct cli_state
*cli_win
= NULL
;
317 uint16_t fnum
= (uint16_t)-1;
319 const char *file
= "file";
320 const char *symlnk_dangling
= "dangling";
321 const char *symlnk_dst_dangling
= "xxxxxxx";
322 const char *symlnk_in_share
= "symlnk_in_share";
323 const char *symlnk_dst_in_share
= file
;
324 const char *symlnk_outside_share
= "symlnk_outside_share";
325 const char *symlnk_dst_outside_share
= "/etc/passwd";
326 struct posix_test_entry entries
[] = {
331 .attr_win
= FILE_ATTRIBUTE_ARCHIVE
,
332 .attr_lin
= FILE_ATTRIBUTE_ARCHIVE
,
334 .name
= symlnk_dangling
,
335 .target
= symlnk_dst_dangling
,
336 .expected
= symlnk_dangling
,
337 .attr_win
= FILE_ATTRIBUTE_INVALID
,
338 .attr_lin
= FILE_ATTRIBUTE_NORMAL
,
340 .name
= symlnk_in_share
,
341 .target
= symlnk_dst_in_share
,
342 .expected
= symlnk_in_share
,
343 .attr_win
= FILE_ATTRIBUTE_ARCHIVE
,
344 .attr_lin
= FILE_ATTRIBUTE_NORMAL
,
346 .name
= symlnk_outside_share
,
347 .target
= symlnk_dst_outside_share
,
348 .expected
= symlnk_outside_share
,
349 .attr_win
= FILE_ATTRIBUTE_INVALID
,
350 .attr_lin
= FILE_ATTRIBUTE_NORMAL
,
355 struct posix_test_state _state
= {
356 .entries
= &entries
[0],
358 struct posix_test_state
*state
= &_state
;
360 bool correct
= false;
362 frame
= talloc_stackframe();
364 printf("Starting POSIX-LS-SINGLE test\n");
366 if (!torture_open_connection(&cli_unix
, 0)) {
371 if (!torture_init_connection(&cli_win
)) {
376 status
= smbXcli_negprot(cli_win
->conn
,
378 lp_client_min_protocol(),
379 lp_client_max_protocol(),
383 if (!NT_STATUS_IS_OK(status
)) {
384 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
389 status
= cli_session_setup_creds(cli_win
, torture_creds
);
390 if (!NT_STATUS_IS_OK(status
)) {
391 printf("smb2cli_sesssetup returned %s\n", nt_errstr(status
));
396 status
= cli_tree_connect(cli_win
, share
, "?????", NULL
);
397 if (!NT_STATUS_IS_OK(status
)) {
398 printf("cli_tree_connect returned %s\n", nt_errstr(status
));
402 torture_conn_set_sockopt(cli_unix
);
403 torture_conn_set_sockopt(cli_win
);
405 status
= torture_setup_unix_extensions(cli_unix
);
406 if (!NT_STATUS_IS_OK(status
)) {
411 cli_posix_unlink(cli_unix
, file
);
412 cli_posix_unlink(cli_unix
, symlnk_dangling
);
413 cli_posix_unlink(cli_unix
, symlnk_in_share
);
414 cli_posix_unlink(cli_unix
, symlnk_outside_share
);
416 status
= cli_posix_open(cli_unix
,
421 if (!NT_STATUS_IS_OK(status
)) {
422 printf("cli_posix_open of %s failed error %s\n",
428 status
= cli_close(cli_unix
, fnum
);
429 if (!NT_STATUS_IS_OK(status
)) {
430 printf("cli_close failed %s\n", nt_errstr(status
));
435 for (i
= 0; entries
[i
].name
!= NULL
; i
++) {
436 if (entries
[i
].target
== NULL
) {
439 status
= cli_posix_symlink(cli_unix
,
442 if (!NT_STATUS_IS_OK(status
)) {
443 printf("POSIX symlink of %s failed (%s)\n",
444 symlnk_dangling
, nt_errstr(status
));
449 printf("Doing Windows ls single\n");
450 state
->flavour
= WINDOWS
;
452 cli_list(cli_win
, file
, 0, posix_ls_fn
, state
);
453 cli_list(cli_win
, symlnk_dangling
, 0, posix_ls_fn
, state
);
454 cli_list(cli_win
, symlnk_outside_share
, 0, posix_ls_fn
, state
);
455 cli_list(cli_win
, symlnk_in_share
, 0, posix_ls_fn
, state
);
457 if (!posix_test_entry_check(state
, file
, true, 0)) {
460 if (!posix_test_entry_check(state
, symlnk_dangling
, false, 0)) {
463 if (!posix_test_entry_check(state
, symlnk_outside_share
, false, 0)) {
466 if (!posix_test_entry_check(state
, symlnk_in_share
, true, 0)) {
470 posix_test_entries_reset(state
);
472 printf("Doing POSIX ls single\n");
473 state
->flavour
= POSIX
;
475 cli_list(cli_unix
, file
, 0, posix_ls_fn
, state
);
476 cli_list(cli_unix
, symlnk_dangling
, 0, posix_ls_fn
, state
);
477 cli_list(cli_unix
, symlnk_outside_share
, 0, posix_ls_fn
, state
);
478 cli_list(cli_unix
, symlnk_in_share
, 0, posix_ls_fn
, state
);
480 if (!posix_test_entry_check(state
, file
, true, 0)) {
483 if (!posix_test_entry_check(state
,
486 strlen(symlnk_dst_dangling
)))
490 if (!posix_test_entry_check(state
,
491 symlnk_outside_share
,
493 strlen(symlnk_dst_outside_share
)))
497 if (!posix_test_entry_check(state
,
500 strlen(symlnk_dst_in_share
))) {
504 printf("POSIX-LS-SINGLE test passed\n");
508 cli_posix_unlink(cli_unix
, file
);
509 cli_posix_unlink(cli_unix
, symlnk_dangling
);
510 cli_posix_unlink(cli_unix
, symlnk_in_share
);
511 cli_posix_unlink(cli_unix
, symlnk_outside_share
);
513 if (!torture_close_connection(cli_unix
)) {
516 if (!torture_close_connection(cli_win
)) {
525 Test POSIX readlink of symlinks
527 bool run_posix_readlink_test(int dummy
)
529 TALLOC_CTX
*frame
= NULL
;
530 struct cli_state
*cli_unix
= NULL
;
531 uint16_t fnum
= (uint16_t)-1;
533 const char *file
= "file";
534 const char *symlnk_dangling
= "dangling";
535 const char *symlnk_dst_dangling
= "xxxxxxx";
536 const char *symlnk_in_share
= "symlnk_in_share";
537 const char *symlnk_dst_in_share
= file
;
538 const char *symlnk_outside_share
= "symlnk_outside_share";
539 const char *symlnk_dst_outside_share
= "/etc/passwd";
540 struct posix_test_entry entries
[] = {
542 .name
= symlnk_dangling
,
543 .target
= symlnk_dst_dangling
,
544 .expected
= symlnk_dangling
,
546 .name
= symlnk_in_share
,
547 .target
= symlnk_dst_in_share
,
548 .expected
= symlnk_in_share
,
550 .name
= symlnk_outside_share
,
551 .target
= symlnk_dst_outside_share
,
552 .expected
= symlnk_outside_share
,
557 struct posix_test_state _state
= {
558 .entries
= &entries
[0],
560 struct posix_test_state
*state
= &_state
;
562 bool correct
= false;
564 frame
= talloc_stackframe();
566 printf("Starting POSIX-READLINK test\n");
567 state
->flavour
= POSIX
;
569 if (!torture_open_connection(&cli_unix
, 0)) {
574 torture_conn_set_sockopt(cli_unix
);
576 status
= torture_setup_unix_extensions(cli_unix
);
577 if (!NT_STATUS_IS_OK(status
)) {
582 cli_posix_unlink(cli_unix
, file
);
583 cli_posix_unlink(cli_unix
, symlnk_dangling
);
584 cli_posix_unlink(cli_unix
, symlnk_in_share
);
585 cli_posix_unlink(cli_unix
, symlnk_outside_share
);
587 status
= cli_posix_open(cli_unix
,
592 if (!NT_STATUS_IS_OK(status
)) {
593 printf("cli_posix_open of %s failed error %s\n",
599 status
= cli_close(cli_unix
, fnum
);
600 if (!NT_STATUS_IS_OK(status
)) {
601 printf("cli_close failed %s\n", nt_errstr(status
));
606 for (i
= 0; entries
[i
].name
!= NULL
; i
++) {
607 status
= cli_posix_symlink(cli_unix
,
610 if (!NT_STATUS_IS_OK(status
)) {
611 printf("POSIX symlink of %s failed (%s)\n",
612 symlnk_dangling
, nt_errstr(status
));
617 for (i
= 0; entries
[i
].name
!= NULL
; i
++) {
620 status
= cli_readlink(
627 if (!NT_STATUS_IS_OK(status
)) {
628 printf("POSIX readlink on %s failed (%s)\n",
629 entries
[i
].name
, nt_errstr(status
));
632 if (strequal(target
, entries
[i
].target
)) {
633 entries
[i
].ok
= true;
634 entries
[i
].returned_size
= strlen(target
);
638 if (!posix_test_entry_check(state
,
641 strlen(symlnk_dst_dangling
)))
645 if (!posix_test_entry_check(state
,
646 symlnk_outside_share
,
648 strlen(symlnk_dst_outside_share
)))
652 if (!posix_test_entry_check(state
,
655 strlen(symlnk_dst_in_share
))) {
659 printf("POSIX-READLINK test passed\n");
663 cli_posix_unlink(cli_unix
, file
);
664 cli_posix_unlink(cli_unix
, symlnk_dangling
);
665 cli_posix_unlink(cli_unix
, symlnk_in_share
);
666 cli_posix_unlink(cli_unix
, symlnk_outside_share
);
668 if (!torture_close_connection(cli_unix
)) {
677 Test POSIX stat of symlinks
679 bool run_posix_stat_test(int dummy
)
681 TALLOC_CTX
*frame
= NULL
;
682 struct cli_state
*cli_unix
= NULL
;
683 uint16_t fnum
= (uint16_t)-1;
685 const char *file
= "file";
686 const char *symlnk_dangling
= "dangling";
687 const char *symlnk_dst_dangling
= "xxxxxxx";
688 const char *symlnk_in_share
= "symlnk_in_share";
689 const char *symlnk_dst_in_share
= file
;
690 const char *symlnk_outside_share
= "symlnk_outside_share";
691 const char *symlnk_dst_outside_share
= "/etc/passwd";
692 struct posix_test_entry entries
[] = {
694 .name
= symlnk_dangling
,
695 .target
= symlnk_dst_dangling
,
696 .expected
= symlnk_dangling
,
698 .name
= symlnk_in_share
,
699 .target
= symlnk_dst_in_share
,
700 .expected
= symlnk_in_share
,
702 .name
= symlnk_outside_share
,
703 .target
= symlnk_dst_outside_share
,
704 .expected
= symlnk_outside_share
,
709 struct posix_test_state _state
= {
710 .entries
= &entries
[0],
712 struct posix_test_state
*state
= &_state
;
714 bool correct
= false;
716 frame
= talloc_stackframe();
718 printf("Starting POSIX-STAT test\n");
719 state
->flavour
= POSIX
;
721 if (!torture_open_connection(&cli_unix
, 0)) {
726 torture_conn_set_sockopt(cli_unix
);
728 status
= torture_setup_unix_extensions(cli_unix
);
729 if (!NT_STATUS_IS_OK(status
)) {
734 cli_posix_unlink(cli_unix
, file
);
735 cli_posix_unlink(cli_unix
, symlnk_dangling
);
736 cli_posix_unlink(cli_unix
, symlnk_in_share
);
737 cli_posix_unlink(cli_unix
, symlnk_outside_share
);
739 status
= cli_posix_open(cli_unix
,
744 if (!NT_STATUS_IS_OK(status
)) {
745 printf("cli_posix_open of %s failed error %s\n",
751 status
= cli_close(cli_unix
, fnum
);
752 if (!NT_STATUS_IS_OK(status
)) {
753 printf("cli_close failed %s\n", nt_errstr(status
));
758 for (i
= 0; entries
[i
].name
!= NULL
; i
++) {
759 status
= cli_posix_symlink(cli_unix
,
762 if (!NT_STATUS_IS_OK(status
)) {
763 printf("POSIX symlink of %s failed (%s)\n",
764 symlnk_dangling
, nt_errstr(status
));
769 for (i
= 0; entries
[i
].name
!= NULL
; i
++) {
770 SMB_STRUCT_STAT sbuf
;
772 status
= cli_posix_stat(cli_unix
,
775 if (!NT_STATUS_IS_OK(status
)) {
776 printf("POSIX stat on %s failed (%s)\n",
777 entries
[i
].name
, nt_errstr(status
));
780 entries
[i
].ok
= true;
781 entries
[i
].returned_size
= sbuf
.st_ex_size
;
784 if (!posix_test_entry_check(state
,
787 strlen(symlnk_dst_dangling
)))
791 if (!posix_test_entry_check(state
,
792 symlnk_outside_share
,
794 strlen(symlnk_dst_outside_share
)))
798 if (!posix_test_entry_check(state
,
801 strlen(symlnk_dst_in_share
))) {
805 printf("POSIX-STAT test passed\n");
809 cli_posix_unlink(cli_unix
, file
);
810 cli_posix_unlink(cli_unix
, symlnk_dangling
);
811 cli_posix_unlink(cli_unix
, symlnk_in_share
);
812 cli_posix_unlink(cli_unix
, symlnk_outside_share
);
814 if (!torture_close_connection(cli_unix
)) {
823 Test Creating files and directories directly
826 bool run_posix_symlink_parent_test(int dummy
)
828 TALLOC_CTX
*frame
= NULL
;
829 struct cli_state
*cli_unix
= NULL
;
830 uint16_t fnum
= (uint16_t)-1;
832 const char *parent_dir
= "target_dir";
833 const char *parent_symlink
= "symlink_to_target_dir";
834 const char *fname_real
= "target_dir/file";
835 const char *dname_real
= "target_dir/dir";
836 const char *fname_link
= "symlink_to_target_dir/file";
837 const char *dname_link
= "symlink_to_target_dir/dir";
838 const char *sname_link
= "symlink_to_target_dir/symlink";
839 const char *hname_link
= "symlink_to_target_dir/hardlink";
840 bool correct
= false;
842 frame
= talloc_stackframe();
844 printf("Starting POSIX-SYMLINK-PARENT test\n");
846 if (!torture_open_connection(&cli_unix
, 0)) {
851 torture_conn_set_sockopt(cli_unix
);
853 status
= torture_setup_unix_extensions(cli_unix
);
854 if (!NT_STATUS_IS_OK(status
)) {
859 /* Start with a clean slate. */
860 cli_posix_unlink(cli_unix
, fname_real
);
861 cli_posix_rmdir(cli_unix
, dname_real
);
862 cli_posix_unlink(cli_unix
, fname_link
);
863 cli_posix_rmdir(cli_unix
, dname_link
);
864 cli_posix_unlink(cli_unix
, sname_link
);
865 cli_posix_unlink(cli_unix
, hname_link
);
866 cli_posix_unlink(cli_unix
, parent_symlink
);
867 cli_posix_rmdir(cli_unix
, parent_dir
);
869 /* Create parent_dir. */
870 status
= cli_posix_mkdir(cli_unix
, parent_dir
, 0777);
871 if (!NT_STATUS_IS_OK(status
)) {
872 printf("cli_posix_mkdir of %s failed error %s\n",
877 /* Create symlink to parent_dir. */
878 status
= cli_posix_symlink(cli_unix
,
881 if (!NT_STATUS_IS_OK(status
)) {
882 printf("cli_posix_symlink of %s -> %s failed error %s\n",
888 /* Try and create a directory under the symlink. */
889 status
= cli_posix_mkdir(cli_unix
, dname_link
, 0777);
890 if (!NT_STATUS_IS_OK(status
)) {
891 printf("cli_posix_mkdir of %s failed error %s\n",
896 /* Try and create a file under the symlink. */
897 status
= cli_posix_open(cli_unix
,
902 if (!NT_STATUS_IS_OK(status
)) {
903 printf("cli_posix_open of %s failed error %s\n",
908 status
= cli_close(cli_unix
, fnum
);
909 if (!NT_STATUS_IS_OK(status
)) {
910 printf("cli_close failed %s\n", nt_errstr(status
));
915 /* Try and create a symlink to the file under the symlink. */
916 status
= cli_posix_symlink(cli_unix
,
919 if (!NT_STATUS_IS_OK(status
)) {
920 printf("cli_posix_symlink of %s -> %s failed error %s\n",
927 /* Try and create a hardlink to the file under the symlink. */
928 status
= cli_posix_hardlink(cli_unix
,
931 if (!NT_STATUS_IS_OK(status
)) {
932 printf("cli_posix_hardlink of %s -> %s failed error %s\n",
939 /* Ensure we can delete the symlink via the parent symlink */
940 status
= cli_posix_unlink(cli_unix
, sname_link
);
941 if (!NT_STATUS_IS_OK(status
)) {
942 printf("cli_posix_unlink of %s failed error %s\n",
948 /* Ensure we can delete the hardlink via the parent symlink */
949 status
= cli_posix_unlink(cli_unix
, hname_link
);
950 if (!NT_STATUS_IS_OK(status
)) {
951 printf("cli_posix_unlink of %s failed error %s\n",
957 /* Ensure we can delete the directory via the parent symlink */
958 status
= cli_posix_rmdir(cli_unix
, dname_link
);
959 if (!NT_STATUS_IS_OK(status
)) {
960 printf("cli_posix_rmdir of %s failed error %s\n",
965 /* Ensure we can delete the file via the parent symlink */
966 status
= cli_posix_unlink(cli_unix
, fname_link
);
967 if (!NT_STATUS_IS_OK(status
)) {
968 printf("cli_posix_unlink of %s failed error %s\n",
974 printf("POSIX-SYMLINK-PARENT test passed\n");
978 if (fnum
!= (uint16_t)-1) {
979 cli_close(cli_unix
, fnum
);
981 cli_posix_unlink(cli_unix
, fname_real
);
982 cli_posix_rmdir(cli_unix
, dname_real
);
983 cli_posix_unlink(cli_unix
, fname_link
);
984 cli_posix_rmdir(cli_unix
, dname_link
);
985 cli_posix_unlink(cli_unix
, sname_link
);
986 cli_posix_unlink(cli_unix
, hname_link
);
987 cli_posix_unlink(cli_unix
, parent_symlink
);
988 cli_posix_rmdir(cli_unix
, parent_dir
);
990 if (!torture_close_connection(cli_unix
)) {
999 Ensure we get an error when doing chmod on a symlink,
1000 whether it is pointing to a real object or dangling.
1002 bool run_posix_symlink_chmod_test(int dummy
)
1004 TALLOC_CTX
*frame
= NULL
;
1005 struct cli_state
*cli_unix
= NULL
;
1007 uint16_t fnum
= (uint16_t)-1;
1008 const char *fname_real
= "file_real";
1009 const char *fname_real_symlink
= "file_real_symlink";
1010 const char *nonexist
= "nonexist";
1011 const char *nonexist_symlink
= "dangling_symlink";
1012 bool correct
= false;
1014 frame
= talloc_stackframe();
1016 printf("Starting POSIX-SYMLINK-CHMOD test\n");
1018 if (!torture_open_connection(&cli_unix
, 0)) {
1023 torture_conn_set_sockopt(cli_unix
);
1025 status
= torture_setup_unix_extensions(cli_unix
);
1026 if (!NT_STATUS_IS_OK(status
)) {
1031 /* Start with a clean slate. */
1032 cli_posix_unlink(cli_unix
, fname_real
);
1033 cli_posix_unlink(cli_unix
, fname_real_symlink
);
1034 cli_posix_unlink(cli_unix
, nonexist
);
1035 cli_posix_unlink(cli_unix
, nonexist_symlink
);
1037 /* Create a real file. */
1038 status
= cli_posix_open(cli_unix
,
1043 if (!NT_STATUS_IS_OK(status
)) {
1044 printf("cli_posix_open of %s failed error %s\n",
1049 status
= cli_close(cli_unix
, fnum
);
1050 if (!NT_STATUS_IS_OK(status
)) {
1051 printf("cli_close failed %s\n", nt_errstr(status
));
1054 fnum
= (uint16_t)-1;
1056 /* Create symlink to real target. */
1057 status
= cli_posix_symlink(cli_unix
,
1059 fname_real_symlink
);
1060 if (!NT_STATUS_IS_OK(status
)) {
1061 printf("cli_posix_symlink of %s -> %s failed error %s\n",
1068 /* We should not be able to chmod symlinks that point to something. */
1069 status
= cli_posix_chmod(cli_unix
, fname_real_symlink
, 0777);
1071 /* This should fail with something other than server crashed. */
1072 if (NT_STATUS_IS_OK(status
)) {
1073 printf("cli_posix_chmod of %s succeeded (should have failed)\n",
1074 fname_real_symlink
);
1077 if (NT_STATUS_EQUAL(status
, NT_STATUS_CONNECTION_DISCONNECTED
)) {
1078 /* Oops. Server crashed. */
1079 printf("cli_posix_chmod of %s failed error %s\n",
1084 /* Any other failure is ok. */
1086 /* Now create symlink to non-existing target. */
1087 status
= cli_posix_symlink(cli_unix
,
1090 if (!NT_STATUS_IS_OK(status
)) {
1091 printf("cli_posix_symlink of %s -> %s failed error %s\n",
1098 /* We should not be able to chmod symlinks that point to nothing. */
1099 status
= cli_posix_chmod(cli_unix
, nonexist_symlink
, 0777);
1101 /* This should fail with something other than server crashed. */
1102 if (NT_STATUS_IS_OK(status
)) {
1103 printf("cli_posix_chmod of %s succeeded (should have failed)\n",
1107 if (NT_STATUS_EQUAL(status
, NT_STATUS_CONNECTION_DISCONNECTED
)) {
1108 /* Oops. Server crashed. */
1109 printf("cli_posix_chmod of %s failed error %s\n",
1115 /* Any other failure is ok. */
1116 printf("POSIX-SYMLINK-CHMOD test passed (expected failure was %s)\n",
1121 if (fnum
!= (uint16_t)-1) {
1122 cli_close(cli_unix
, fnum
);
1124 cli_posix_unlink(cli_unix
, fname_real
);
1125 cli_posix_unlink(cli_unix
, fname_real_symlink
);
1126 cli_posix_unlink(cli_unix
, nonexist
);
1127 cli_posix_unlink(cli_unix
, nonexist_symlink
);
1129 if (!torture_close_connection(cli_unix
)) {
1138 Ensure we get an ACL containing OI|IO ACE entries
1139 after we add a default POSIX ACL to a directory.
1140 This will only ever be an SMB1 test as it depends
1141 on POSIX ACL semantics.
1143 bool run_posix_dir_default_acl_test(int dummy
)
1145 TALLOC_CTX
*frame
= NULL
;
1146 struct cli_state
*cli_unix
= NULL
;
1148 uint16_t fnum
= (uint16_t)-1;
1149 const char *dname
= "dir_with_default_acl";
1150 bool correct
= false;
1151 SMB_STRUCT_STAT sbuf
;
1152 size_t acl_size
= 0;
1153 char *aclbuf
= NULL
;
1154 size_t num_file_acls
= 0;
1155 size_t num_dir_acls
= 0;
1156 size_t expected_buflen
;
1157 uint8_t def_acl
[SMB_POSIX_ACL_HEADER_SIZE
+
1158 5*SMB_POSIX_ACL_ENTRY_SIZE
] = {0};
1161 struct security_descriptor
*sd
= NULL
;
1162 bool got_inherit
= false;
1164 frame
= talloc_stackframe();
1166 printf("Starting POSIX-DIR-DEFAULT-ACL test\n");
1168 if (!torture_open_connection(&cli_unix
, 0)) {
1173 torture_conn_set_sockopt(cli_unix
);
1175 status
= torture_setup_unix_extensions(cli_unix
);
1176 if (!NT_STATUS_IS_OK(status
)) {
1181 /* Start with a clean slate. */
1182 cli_posix_unlink(cli_unix
, dname
);
1183 cli_posix_rmdir(cli_unix
, dname
);
1185 status
= cli_posix_mkdir(cli_unix
, dname
, 0777);
1186 if (!NT_STATUS_IS_OK(status
)) {
1187 printf("cli_posix_mkdir of %s failed error %s\n",
1193 /* Do a posix stat to get the owner. */
1194 status
= cli_posix_stat(cli_unix
, dname
, &sbuf
);
1195 if (!NT_STATUS_IS_OK(status
)) {
1196 printf("cli_posix_stat of %s failed %s\n",
1202 /* Get the ACL on the directory. */
1203 status
= cli_posix_getacl(cli_unix
, dname
, frame
, &acl_size
, &aclbuf
);
1204 if (!NT_STATUS_IS_OK(status
)) {
1205 printf("cli_posix_getacl on %s failed %s\n",
1211 if (acl_size
< 6 || SVAL(aclbuf
,0) != SMB_POSIX_ACL_VERSION
) {
1212 printf("%s, unknown POSIX acl version %u.\n",
1214 (unsigned int)CVAL(aclbuf
,0) );
1218 num_file_acls
= SVAL(aclbuf
,2);
1219 num_dir_acls
= SVAL(aclbuf
,4);
1222 * No overflow check, num_*_acls comes from a 16-bit value,
1223 * and we expect expected_buflen (size_t) to be of at least 32
1226 expected_buflen
= SMB_POSIX_ACL_HEADER_SIZE
+
1227 SMB_POSIX_ACL_ENTRY_SIZE
*(num_file_acls
+num_dir_acls
);
1229 if (acl_size
!= expected_buflen
) {
1230 printf("%s, incorrect POSIX acl buffer size "
1231 "(should be %zu, was %zu).\n",
1238 if (num_dir_acls
!= 0) {
1239 printf("%s, POSIX default acl already exists"
1240 "(should be 0, was %zu).\n",
1247 * Get the Windows ACL on the directory.
1248 * Make sure there are no inheritable entries.
1250 status
= cli_ntcreate(cli_unix
,
1253 SEC_STD_READ_CONTROL
,
1259 FILE_DIRECTORY_FILE
,
1263 if (!NT_STATUS_IS_OK(status
)) {
1264 printf("Failed to open directory %s: %s\n",
1270 status
= cli_query_security_descriptor(cli_unix
,
1275 if (!NT_STATUS_IS_OK(status
)) {
1276 printf("Failed to get security descriptor on directory %s: %s\n",
1282 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
1283 struct security_ace
*ace
= &sd
->dacl
->aces
[i
];
1284 if (ace
->flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
1285 SEC_ACE_FLAG_CONTAINER_INHERIT
)) {
1286 printf("security descriptor on directory %s already "
1287 "contains inheritance flags\n",
1289 sec_desc_print(NULL
, stdout
, sd
, true);
1296 /* Construct a new default ACL. */
1297 SSVAL(def_acl
,0,SMB_POSIX_ACL_VERSION
);
1298 SSVAL(def_acl
,2,SMB_POSIX_IGNORE_ACE_ENTRIES
);
1299 SSVAL(def_acl
,4,5); /* num_dir_acls. */
1301 p
= def_acl
+ SMB_POSIX_ACL_HEADER_SIZE
;
1304 SCVAL(p
,0,SMB_POSIX_ACL_USER_OBJ
); /* tagtype. */
1305 SCVAL(p
,1,SMB_POSIX_ACL_READ
|SMB_POSIX_ACL_WRITE
|SMB_POSIX_ACL_EXECUTE
);
1306 p
+= SMB_POSIX_ACL_ENTRY_SIZE
;
1309 SCVAL(p
,0,SMB_POSIX_ACL_GROUP_OBJ
); /* tagtype. */
1310 SCVAL(p
,1,SMB_POSIX_ACL_READ
|SMB_POSIX_ACL_WRITE
|SMB_POSIX_ACL_EXECUTE
);
1311 p
+= SMB_POSIX_ACL_ENTRY_SIZE
;
1314 SCVAL(p
,0,SMB_POSIX_ACL_OTHER
); /* tagtype. */
1315 SCVAL(p
,1,SMB_POSIX_ACL_READ
|SMB_POSIX_ACL_WRITE
|SMB_POSIX_ACL_EXECUTE
);
1316 p
+= SMB_POSIX_ACL_ENTRY_SIZE
;
1318 /* Explicit user. */
1319 SCVAL(p
,0,SMB_POSIX_ACL_USER
); /* tagtype. */
1320 SCVAL(p
,1,SMB_POSIX_ACL_READ
|SMB_POSIX_ACL_WRITE
|SMB_POSIX_ACL_EXECUTE
);
1321 SIVAL(p
,2,sbuf
.st_ex_uid
);
1322 p
+= SMB_POSIX_ACL_ENTRY_SIZE
;
1325 SCVAL(p
,0,SMB_POSIX_ACL_MASK
); /* tagtype. */
1326 SCVAL(p
,1,SMB_POSIX_ACL_READ
|SMB_POSIX_ACL_WRITE
|SMB_POSIX_ACL_EXECUTE
);
1327 p
+= SMB_POSIX_ACL_ENTRY_SIZE
;
1329 /* Set the POSIX default ACL. */
1330 status
= cli_posix_setacl(cli_unix
, dname
, def_acl
, sizeof(def_acl
));
1331 if (!NT_STATUS_IS_OK(status
)) {
1332 printf("cli_posix_setacl on %s failed %s\n",
1339 * Get the Windows ACL on the directory again.
1340 * Now there should be inheritable entries.
1343 status
= cli_query_security_descriptor(cli_unix
,
1348 if (!NT_STATUS_IS_OK(status
)) {
1349 printf("Failed (2) to get security descriptor "
1350 "on directory %s: %s\n",
1356 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
1357 struct security_ace
*ace
= &sd
->dacl
->aces
[i
];
1358 if (ace
->flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
1359 SEC_ACE_FLAG_CONTAINER_INHERIT
)) {
1366 printf("security descriptor on directory %s does not "
1367 "contain inheritance flags\n",
1369 sec_desc_print(NULL
, stdout
, sd
, true);
1373 cli_close(cli_unix
, fnum
);
1374 fnum
= (uint16_t)-1;
1375 printf("POSIX-DIR-DEFAULT-ACL test passed\n");
1382 if (fnum
!= (uint16_t)-1) {
1383 cli_close(cli_unix
, fnum
);
1385 cli_posix_unlink(cli_unix
, dname
);
1386 cli_posix_rmdir(cli_unix
, dname
);
1388 if (!torture_close_connection(cli_unix
)) {
1397 Ensure we can rename a symlink whether it is
1398 pointing to a real object or dangling.
1400 bool run_posix_symlink_rename_test(int dummy
)
1402 TALLOC_CTX
*frame
= NULL
;
1403 struct cli_state
*cli_unix
= NULL
;
1405 uint16_t fnum
= (uint16_t)-1;
1406 const char *fname_real
= "file_real";
1407 const char *fname_real_symlink
= "file_real_symlink";
1408 const char *fname_real_symlink_newname
= "rename_file_real_symlink";
1409 const char *nonexist
= "nonexist";
1410 const char *nonexist_symlink
= "dangling_symlink";
1411 const char *nonexist_symlink_newname
= "dangling_symlink_rename";
1412 bool correct
= false;
1414 frame
= talloc_stackframe();
1416 printf("Starting POSIX-SYMLINK-RENAME test\n");
1418 if (!torture_open_connection(&cli_unix
, 0)) {
1423 torture_conn_set_sockopt(cli_unix
);
1425 status
= torture_setup_unix_extensions(cli_unix
);
1426 if (!NT_STATUS_IS_OK(status
)) {
1431 /* Start with a clean slate. */
1432 cli_posix_unlink(cli_unix
, fname_real
);
1433 cli_posix_unlink(cli_unix
, fname_real_symlink
);
1434 cli_posix_unlink(cli_unix
, fname_real_symlink_newname
);
1435 cli_posix_unlink(cli_unix
, nonexist
);
1436 cli_posix_unlink(cli_unix
, nonexist_symlink
);
1437 cli_posix_unlink(cli_unix
, nonexist_symlink_newname
);
1439 /* Create a real file. */
1440 status
= cli_posix_open(cli_unix
,
1445 if (!NT_STATUS_IS_OK(status
)) {
1446 printf("cli_posix_open of %s failed error %s\n",
1451 status
= cli_close(cli_unix
, fnum
);
1452 if (!NT_STATUS_IS_OK(status
)) {
1453 printf("cli_close failed %s\n", nt_errstr(status
));
1456 fnum
= (uint16_t)-1;
1458 /* Create symlink to real target. */
1459 status
= cli_posix_symlink(cli_unix
,
1461 fname_real_symlink
);
1462 if (!NT_STATUS_IS_OK(status
)) {
1463 printf("cli_posix_symlink of %s -> %s failed error %s\n",
1470 /* Ensure we can rename the symlink to the real file. */
1471 status
= cli_rename(cli_unix
,
1473 fname_real_symlink_newname
,
1475 if (!NT_STATUS_IS_OK(status
)) {
1476 printf("cli_rename of %s -> %s failed %s\n",
1478 fname_real_symlink_newname
,
1483 /* Now create symlink to non-existing target. */
1484 status
= cli_posix_symlink(cli_unix
,
1487 if (!NT_STATUS_IS_OK(status
)) {
1488 printf("cli_posix_symlink of %s -> %s failed error %s\n",
1495 /* Ensure we can rename the dangling symlink. */
1496 status
= cli_rename(cli_unix
,
1498 nonexist_symlink_newname
,
1500 if (!NT_STATUS_IS_OK(status
)) {
1501 printf("cli_rename of %s -> %s failed %s\n",
1503 nonexist_symlink_newname
,
1508 printf("POSIX-SYMLINK-RENAME test passed\n");
1512 if (fnum
!= (uint16_t)-1) {
1513 cli_close(cli_unix
, fnum
);
1515 cli_posix_unlink(cli_unix
, fname_real
);
1516 cli_posix_unlink(cli_unix
, fname_real_symlink
);
1517 cli_posix_unlink(cli_unix
, fname_real_symlink_newname
);
1518 cli_posix_unlink(cli_unix
, nonexist
);
1519 cli_posix_unlink(cli_unix
, nonexist_symlink
);
1520 cli_posix_unlink(cli_unix
, nonexist_symlink_newname
);
1522 if (!torture_close_connection(cli_unix
)) {
1530 /* List of info levels to try with a POSIX symlink path. */
1535 } posix_smb1_qpath_array
[] = {
1536 { SMB_INFO_STANDARD
, "SMB_INFO_STANDARD"},
1537 { SMB_INFO_QUERY_EA_SIZE
, "SMB_INFO_QUERY_EA_SIZE"},
1538 { SMB_INFO_IS_NAME_VALID
, "SMB_INFO_IS_NAME_VALID"},
1539 { SMB_INFO_QUERY_EAS_FROM_LIST
, "SMB_INFO_QUERY_EAS_FROM_LIST"},
1540 { SMB_INFO_QUERY_ALL_EAS
, "SMB_INFO_QUERY_ALL_EAS"},
1541 { SMB_FILE_BASIC_INFORMATION
, "SMB_FILE_BASIC_INFORMATION"},
1542 { SMB_FILE_STANDARD_INFORMATION
, "SMB_FILE_STANDARD_INFORMATION"},
1543 { SMB_FILE_EA_INFORMATION
, "SMB_FILE_EA_INFORMATION"},
1544 { SMB_FILE_ALTERNATE_NAME_INFORMATION
,"SMB_FILE_ALTERNATE_NAME_INFORMATION"},
1545 { SMB_QUERY_FILE_NAME_INFO
, "SMB_QUERY_FILE_NAME_INFO"},
1546 { SMB_FILE_NORMALIZED_NAME_INFORMATION
,"SMB_FILE_NORMALIZED_NAME_INFORMATION"},
1547 { SMB_FILE_ALLOCATION_INFORMATION
, "SMB_FILE_ALLOCATION_INFORMATION"},
1548 { SMB_FILE_END_OF_FILE_INFORMATION
, "SMB_FILE_END_OF_FILE_INFORMATION"},
1549 { SMB_FILE_ALL_INFORMATION
, "SMB_FILE_ALL_INFORMATION"},
1550 { SMB_FILE_INTERNAL_INFORMATION
, "SMB_FILE_INTERNAL_INFORMATION"},
1551 { SMB_FILE_ACCESS_INFORMATION
, "SMB_FILE_ACCESS_INFORMATION"},
1552 { SMB_FILE_NAME_INFORMATION
, "SMB_FILE_NAME_INFORMATION"},
1553 { SMB_FILE_DISPOSITION_INFORMATION
, "SMB_FILE_DISPOSITION_INFORMATION"},
1554 { SMB_FILE_POSITION_INFORMATION
, "SMB_FILE_POSITION_INFORMATION"},
1555 { SMB_FILE_MODE_INFORMATION
, "SMB_FILE_MODE_INFORMATION"},
1556 { SMB_FILE_ALIGNMENT_INFORMATION
, "SMB_FILE_ALIGNMENT_INFORMATION"},
1557 { SMB_FILE_STREAM_INFORMATION
, "SMB_FILE_STREAM_INFORMATION"},
1558 { SMB_FILE_COMPRESSION_INFORMATION
, "SMB_FILE_COMPRESSION_INFORMATION"},
1559 { SMB_FILE_NETWORK_OPEN_INFORMATION
, "SMB_FILE_NETWORK_OPEN_INFORMATION"},
1560 { SMB_FILE_ATTRIBUTE_TAG_INFORMATION
, "SMB_FILE_ATTRIBUTE_TAG_INFORMATION"},
1561 { SMB_QUERY_FILE_UNIX_BASIC
, "SMB_QUERY_FILE_UNIX_BASIC"},
1562 { SMB_QUERY_FILE_UNIX_INFO2
, "SMB_QUERY_FILE_UNIX_INFO2"},
1563 { SMB_QUERY_FILE_UNIX_LINK
, "SMB_QUERY_FILE_UNIX_LINK"},
1564 { SMB_QUERY_POSIX_ACL
, "SMB_QUERY_POSIX_ACL"},
1565 { SMB_QUERY_POSIX_LOCK
, "SMB_QUERY_POSIX_LOCK"},
1568 static NTSTATUS
do_qpath(TALLOC_CTX
*ctx
,
1569 struct cli_state
*cli_unix
,
1575 if (posix_smb1_qpath_array
[i
].level
==
1576 SMB_INFO_QUERY_EAS_FROM_LIST
) {
1580 uint8_t *rparam
= NULL
;
1581 uint8_t *rdata
= NULL
;
1582 uint32_t rbytes
= 0;
1584 /* Set up an EA list with 'a' as the single name. */
1586 SCVAL(data
,4, 2); /* namelen. */
1588 SCVAL(data
,6, '\0'); /* name. */
1589 SCVAL(data
,7, '\0'); /* padding. */
1591 SSVAL(&setup
, 0, TRANSACT2_QPATHINFO
);
1593 param
= talloc_zero_array(ctx
, uint8_t, 6);
1594 if (param
== NULL
) {
1595 return NT_STATUS_NO_MEMORY
;
1597 SSVAL(param
, 0, SMB_INFO_QUERY_EAS_FROM_LIST
);
1598 param
= trans2_bytes_push_str(param
,
1599 smbXcli_conn_use_unicode(cli_unix
->conn
),
1603 if (param
== NULL
) {
1604 return NT_STATUS_NO_MEMORY
;
1607 status
= cli_trans(ctx
,
1615 param
, talloc_get_size(param
), talloc_get_size(param
),
1619 &rparam
, 0, &rbytes
,
1620 &rdata
, 0, &rbytes
);
1621 TALLOC_FREE(rparam
);
1624 uint8_t *rdata
= NULL
;
1625 uint32_t num_rdata
= 0;
1627 status
= cli_qpathinfo(ctx
,
1630 posix_smb1_qpath_array
[i
].level
,
1632 65534, /* max_rdata */
1638 * We don't care what came back, so long as the
1639 * server didn't crash.
1641 if (NT_STATUS_EQUAL(status
,
1642 NT_STATUS_CONNECTION_DISCONNECTED
)) {
1643 printf("cli_qpathinfo of %s failed error "
1644 "NT_STATUS_CONNECTION_DISCONNECTED\n",
1649 printf("cli_qpathinfo info %x (%s) of %s got %s "
1650 "(this is not an error)\n",
1651 (unsigned int)posix_smb1_qpath_array
[i
].level
,
1652 posix_smb1_qpath_array
[i
].name
,
1656 return NT_STATUS_OK
;
1660 Ensure we can call SMB1 getpathinfo in a symlink,
1661 pointing to a real object or dangling. We mostly
1662 expect errors, but the server must not crash.
1664 bool run_posix_symlink_getpathinfo_test(int dummy
)
1666 TALLOC_CTX
*frame
= NULL
;
1667 struct cli_state
*cli_unix
= NULL
;
1669 uint16_t fnum
= (uint16_t)-1;
1670 const char *fname_real
= "file_getpath_real";
1671 const char *fname_real_symlink
= "file_real_getpath_symlink";
1672 const char *nonexist
= "nonexist_getpath";
1673 const char *nonexist_symlink
= "dangling_getpath_symlink";
1674 bool correct
= false;
1677 frame
= talloc_stackframe();
1679 printf("Starting POSIX-SYMLINK-GETPATHINFO test\n");
1681 if (!torture_open_connection(&cli_unix
, 0)) {
1686 torture_conn_set_sockopt(cli_unix
);
1688 status
= torture_setup_unix_extensions(cli_unix
);
1689 if (!NT_STATUS_IS_OK(status
)) {
1694 /* Start with a clean slate. */
1695 cli_posix_unlink(cli_unix
, fname_real
);
1696 cli_posix_unlink(cli_unix
, fname_real_symlink
);
1697 cli_posix_unlink(cli_unix
, nonexist
);
1698 cli_posix_unlink(cli_unix
, nonexist_symlink
);
1700 /* Create a real file. */
1701 status
= cli_posix_open(cli_unix
,
1706 if (!NT_STATUS_IS_OK(status
)) {
1707 printf("cli_posix_open of %s failed error %s\n",
1712 status
= cli_close(cli_unix
, fnum
);
1713 if (!NT_STATUS_IS_OK(status
)) {
1714 printf("cli_close failed %s\n", nt_errstr(status
));
1717 fnum
= (uint16_t)-1;
1719 /* Create symlink to real target. */
1720 status
= cli_posix_symlink(cli_unix
,
1722 fname_real_symlink
);
1723 if (!NT_STATUS_IS_OK(status
)) {
1724 printf("cli_posix_symlink of %s -> %s failed error %s\n",
1731 /* Now create symlink to non-existing target. */
1732 status
= cli_posix_symlink(cli_unix
,
1735 if (!NT_STATUS_IS_OK(status
)) {
1736 printf("cli_posix_symlink of %s -> %s failed error %s\n",
1743 for (i
= 0; i
< ARRAY_SIZE(posix_smb1_qpath_array
); i
++) {
1744 status
= do_qpath(frame
,
1748 if (!NT_STATUS_IS_OK(status
)) {
1751 status
= do_qpath(frame
,
1755 if (!NT_STATUS_IS_OK(status
)) {
1760 printf("POSIX-SYMLINK-GETPATHINFO test passed\n");
1764 if (fnum
!= (uint16_t)-1) {
1765 cli_close(cli_unix
, fnum
);
1767 cli_posix_unlink(cli_unix
, fname_real
);
1768 cli_posix_unlink(cli_unix
, fname_real_symlink
);
1769 cli_posix_unlink(cli_unix
, nonexist
);
1770 cli_posix_unlink(cli_unix
, nonexist_symlink
);
1772 if (!torture_close_connection(cli_unix
)) {
1780 /* List of info levels to try with a POSIX symlink path. */
1786 } posix_smb1_setpath_array
[] = {
1787 { SMB_SET_FILE_UNIX_BASIC
, "SMB_SET_FILE_UNIX_BASIC", 100},
1788 { SMB_SET_FILE_UNIX_INFO2
, "SMB_SET_FILE_UNIX_INFO2", 116},
1789 { SMB_SET_FILE_UNIX_LINK
, "SMB_SET_FILE_UNIX_LINK", 8},
1790 { SMB_SET_FILE_UNIX_HLINK
, "SMB_SET_FILE_UNIX_HLINK", 8},
1791 { SMB_SET_POSIX_ACL
, "SMB_SET_POSIX_ACL", 6},
1792 { SMB_SET_POSIX_LOCK
, "SMB_SET_POSIX_LOCK", 24},
1793 { SMB_INFO_STANDARD
, "SMB_INFO_STANDARD", 12},
1794 { SMB_INFO_SET_EA
, "SMB_INFO_SET_EA", 10},
1795 { SMB_FILE_BASIC_INFORMATION
, "SMB_FILE_BASIC_INFORMATION", 36},
1796 { SMB_SET_FILE_ALLOCATION_INFO
, "SMB_SET_FILE_ALLOCATION_INFO", 8},
1797 { SMB_SET_FILE_END_OF_FILE_INFO
,"SMB_SET_FILE_END_OF_FILE_INFO",8},
1798 { SMB_SET_FILE_DISPOSITION_INFO
,"SMB_SET_FILE_DISPOSITION_INFO",1},
1799 { SMB_FILE_POSITION_INFORMATION
,"SMB_FILE_POSITION_INFORMATION",8},
1800 { SMB_FILE_FULL_EA_INFORMATION
, "SMB_FILE_FULL_EA_INFORMATION",10},
1801 { SMB_FILE_MODE_INFORMATION
, "SMB_FILE_MODE_INFORMATION", 4},
1802 { SMB_FILE_SHORT_NAME_INFORMATION
,"SMB_FILE_SHORT_NAME_INFORMATION",12},
1803 { SMB_FILE_RENAME_INFORMATION
,"SMB_FILE_RENAME_INFORMATION", 20},
1804 { SMB_FILE_LINK_INFORMATION
, "SMB_FILE_LINK_INFORMATION", 20},
1807 static NTSTATUS
do_setpath(TALLOC_CTX
*ctx
,
1808 struct cli_state
*cli_unix
,
1813 uint8_t *data
= NULL
;
1815 data
= talloc_zero_array(ctx
,
1817 posix_smb1_setpath_array
[i
].data_len
);
1819 return NT_STATUS_NO_MEMORY
;
1822 status
= cli_setpathinfo(cli_unix
,
1823 posix_smb1_setpath_array
[i
].level
,
1826 posix_smb1_setpath_array
[i
].data_len
);
1830 * We don't care what came back, so long as the
1831 * server didn't crash.
1833 if (NT_STATUS_EQUAL(status
,
1834 NT_STATUS_CONNECTION_DISCONNECTED
)) {
1835 printf("cli_setpathinfo info %x (%s) of %s failed"
1836 "error NT_STATUS_CONNECTION_DISCONNECTED\n",
1837 (unsigned int)posix_smb1_setpath_array
[i
].level
,
1838 posix_smb1_setpath_array
[i
].name
,
1843 printf("cli_setpathinfo info %x (%s) of %s got %s "
1844 "(this is not an error)\n",
1845 (unsigned int)posix_smb1_setpath_array
[i
].level
,
1846 posix_smb1_setpath_array
[i
].name
,
1850 return NT_STATUS_OK
;
1854 Ensure we can call SMB1 setpathinfo in a symlink,
1855 pointing to a real object or dangling. We mostly
1856 expect errors, but the server must not crash.
1858 bool run_posix_symlink_setpathinfo_test(int dummy
)
1860 TALLOC_CTX
*frame
= NULL
;
1861 struct cli_state
*cli_unix
= NULL
;
1863 uint16_t fnum
= (uint16_t)-1;
1864 const char *fname_real
= "file_setpath_real";
1865 const char *fname_real_symlink
= "file_real_setpath_symlink";
1866 const char *nonexist
= "nonexist_setpath";
1867 const char *nonexist_symlink
= "dangling_setpath_symlink";
1868 bool correct
= false;
1871 frame
= talloc_stackframe();
1873 printf("Starting POSIX-SYMLINK-SETPATHINFO test\n");
1875 if (!torture_open_connection(&cli_unix
, 0)) {
1880 torture_conn_set_sockopt(cli_unix
);
1882 status
= torture_setup_unix_extensions(cli_unix
);
1883 if (!NT_STATUS_IS_OK(status
)) {
1888 /* Start with a clean slate. */
1889 cli_posix_unlink(cli_unix
, fname_real
);
1890 cli_posix_unlink(cli_unix
, fname_real_symlink
);
1891 cli_posix_unlink(cli_unix
, nonexist
);
1892 cli_posix_unlink(cli_unix
, nonexist_symlink
);
1894 /* Create a real file. */
1895 status
= cli_posix_open(cli_unix
,
1900 if (!NT_STATUS_IS_OK(status
)) {
1901 printf("cli_posix_open of %s failed error %s\n",
1906 status
= cli_close(cli_unix
, fnum
);
1907 if (!NT_STATUS_IS_OK(status
)) {
1908 printf("cli_close failed %s\n", nt_errstr(status
));
1911 fnum
= (uint16_t)-1;
1913 /* Create symlink to real target. */
1914 status
= cli_posix_symlink(cli_unix
,
1916 fname_real_symlink
);
1917 if (!NT_STATUS_IS_OK(status
)) {
1918 printf("cli_posix_symlink of %s -> %s failed error %s\n",
1925 /* Now create symlink to non-existing target. */
1926 status
= cli_posix_symlink(cli_unix
,
1929 if (!NT_STATUS_IS_OK(status
)) {
1930 printf("cli_posix_symlink of %s -> %s failed error %s\n",
1937 for (i
= 0; i
< ARRAY_SIZE(posix_smb1_setpath_array
); i
++) {
1938 status
= do_setpath(frame
,
1942 if (!NT_STATUS_IS_OK(status
)) {
1945 status
= do_setpath(frame
,
1949 if (!NT_STATUS_IS_OK(status
)) {
1954 printf("POSIX-SYMLINK-SETPATHINFO test passed\n");
1958 if (fnum
!= (uint16_t)-1) {
1959 cli_close(cli_unix
, fnum
);
1961 cli_posix_unlink(cli_unix
, fname_real
);
1962 cli_posix_unlink(cli_unix
, fname_real_symlink
);
1963 cli_posix_unlink(cli_unix
, nonexist
);
1964 cli_posix_unlink(cli_unix
, nonexist_symlink
);
1966 if (!torture_close_connection(cli_unix
)) {