2021-12-07 12:34:38 -08:00
#!/bin/sh
if [ $# -lt 7 ] ; then
2022-04-22 15:34:11 +02:00
cat <<EOF
2021-12-07 12:34:38 -08:00
Usage: test_symlink_traversal_smb1_posix.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT
EOF
2022-04-22 15:34:11 +02:00
exit 1
2021-12-07 12:34:38 -08:00
fi
SERVER = " ${ 1 } "
SERVER_IP = " ${ 2 } "
USERNAME = " ${ 3 } "
PASSWORD = " ${ 4 } "
LOCAL_PATH = " ${ 5 } "
PREFIX = " ${ 6 } "
SMBCLIENT = " ${ 7 } "
SMBCLIENT = " $VALGRIND ${ SMBCLIENT } "
shift 6
incdir = $( dirname " $0 " ) /../../../testprogs/blackbox
. " $incdir " /subunit.sh
failed = 0
# Do not let deprecated option warnings muck this up
SAMBA_DEPRECATED_SUPPRESS = 1
export SAMBA_DEPRECATED_SUPPRESS
# Define the test environment/filenames.
#
share_test_dir = " $LOCAL_PATH "
#
# These files/directories will be created.
#
2024-08-07 16:28:22 +02:00
file_outside_share = " ${ TMPDIR :- /tmp } /symlink_traverse_test_file. $$ "
dir_outside_share = " ${ TMPDIR :- /tmp } /symlink_traverse_test_dir. $$ "
file_outside_share_noperms = " ${ TMPDIR :- /tmp } /symlink_traverse_test_file_noperm. $$ "
dir_outside_share_noperms = " ${ TMPDIR :- /tmp } /symlink_traverse_test_dir_noperm. $$ "
2021-12-07 12:34:38 -08:00
#
# These two objects do not exist.
#
2024-08-07 16:28:22 +02:00
file_outside_share_noexist = " ${ TMPDIR :- /tmp } /symlink_traverse_test_noexist. $$ "
dir_outside_share_noexist = " ${ TMPDIR :- /tmp } /symlink_traverse_test_dir_noexist. $$ "
2021-12-07 12:34:38 -08:00
#
# Cleanup function.
#
do_cleanup( )
{
2022-04-22 15:34:11 +02:00
(
#subshell.
cd " $share_test_dir " || return
rm -f "file_exists"
rm -f "symlink_noexist"
rm -f "symlink_file_outside_share"
rm -f "symlink_file_outside_share_noexist"
rm -f "symlink_dir_outside_share"
rm -f "symlink_dir_outside_share_noexist"
rm -f "symlink_file_outside_share_noperms"
rm -f "symlink_dir_outside_share_noperms"
rm -rf "emptydir"
# Links inside share.
rm -f "symlink_file_inside_share_noperms"
rm -f "file_inside_share_noperms"
rm -f "symlink_dir_inside_share_noperms"
chmod 755 "dir_inside_share_noperms"
rm -rf "dir_inside_share_noperms"
)
rm -f " $file_outside_share "
rm -rf " $dir_outside_share "
rm -f " $file_outside_share_noperms "
rm -rf " $dir_outside_share_noperms "
2021-12-07 12:34:38 -08:00
}
#
# Ensure we start from a clean slate.
#
do_cleanup
#
# Create the test files/directories/symlinks.
#
# File/directory explicitly outside share.
touch " $file_outside_share "
mkdir " $dir_outside_share "
# File/directory explicitly outside share with permission denied.
touch " $file_outside_share_noperms "
chmod 0 " $file_outside_share_noperms "
mkdir " $dir_outside_share_noperms "
chmod 0 " $dir_outside_share_noperms "
#
# Create links to these objects inside the share definition.
(
2022-04-22 15:34:11 +02:00
#subshell.
cd " $share_test_dir " || return
touch "file_exists"
ln -s "noexist" "symlink_noexist"
ln -s " $file_outside_share " "symlink_file_outside_share"
ln -s " $file_outside_share_noexist " "symlink_file_outside_share_noexist"
ln -s " $dir_outside_share " "symlink_dir_outside_share"
ln -s " $dir_outside_share_noexist " "symlink_dir_outside_share_noexist"
ln -s " $file_outside_share_noperms " "symlink_file_outside_share_noperms"
ln -s " $dir_outside_share_noperms " "symlink_dir_outside_share_noperms"
#
# Create the identical symlink set underneath "emptydir"
mkdir "emptydir"
(
#subshell
cd "emptydir" || return
touch "file_exists"
ln -s "noexist" "symlink_noexist"
ln -s " $file_outside_share " "symlink_file_outside_share"
ln -s " $file_outside_share_noexist " "symlink_file_outside_share_noexist"
ln -s " $dir_outside_share " "symlink_dir_outside_share"
ln -s " $dir_outside_share_noexist " "symlink_dir_outside_share_noexist"
ln -s " $file_outside_share_noperms " "symlink_file_outside_share_noperms"
ln -s " $dir_outside_share_noperms " "symlink_dir_outside_share_noperms"
)
#
# Create symlinks to access denied file and directory
# objects within the share
touch "file_inside_share_noperms"
chmod 0 "file_inside_share_noperms"
ln -s "file_inside_share_noperms" "symlink_file_inside_share_noperms"
mkdir "dir_inside_share_noperms"
touch "dir_inside_share_noperms/noperm_file_exists"
chmod 0 "dir_inside_share_noperms"
ln -s "dir_inside_share_noperms" "symlink_dir_inside_share_noperms"
2021-12-07 12:34:38 -08:00
)
#
# smbclient function given command, path, expected error, and posix.
#
smbclient_expect_error( )
{
2022-04-22 15:34:11 +02:00
filecmd = " $1 "
filename1 = " $2 "
filename2 = " $3 "
expected_error = " $4 "
tmpfile = $PREFIX /smbclient_interactive_prompt_commands
cat >" $tmpfile " <<EOF
2021-12-07 12:34:38 -08:00
posix
$filecmd $filename1 $filename2
quit
EOF
2022-04-22 15:34:11 +02:00
cmd = 'CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I$SERVER_IP -mNT1 < $tmpfile 2>&1'
eval echo " $cmd "
out = $( eval " $cmd " )
ret = $?
rm -f " $tmpfile "
2021-12-07 12:34:38 -08:00
2022-04-22 15:34:11 +02:00
if [ $ret != 0 ] ; then
printf "%s\n" " $out "
printf "failed accessing local_symlinks with error %s\n" " $ret "
return 1
fi
2021-12-07 12:34:38 -08:00
2022-04-22 15:34:11 +02:00
if [ " $expected_error " = "NT_STATUS_OK" ] ; then
printf "%s" " $out " | grep -v "NT_STATUS_"
else
printf "%s" " $out " | grep " $expected_error "
fi
ret = $?
if [ $ret != 0 ] ; then
printf "%s\n" " $out "
printf "failed - should get %s doing posix \"%s %s %s\"\n" " $expected_error " " $filecmd " " $filename1 " " $filename2 "
return 1
fi
2021-12-07 12:34:38 -08:00
}
#
# SMB1+posix tests.
#
test_symlink_traversal_SMB1_posix_onename( )
{
2022-04-22 15:34:11 +02:00
name = " $1 "
do_rename = " $2 "
#
# get commands.
#
# Remember in SMB1+POSIX, "*" is a perfectly valid pathname component,
# and symlinks can be seen, but not necessarily followed.
#
smbclient_expect_error "get" " $name " "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "get" " $name /noexist " "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
smbclient_expect_error "get" " $name /* " "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
smbclient_expect_error "get" " $name /*/noexist " "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
# Now in subdirectory emptydir
smbclient_expect_error "get" " emptydir/ $name " "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "get" " emptydir/ $name /noexist " "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
smbclient_expect_error "get" " emptydir/ $name /* " "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
smbclient_expect_error "get" " emptydir/ $name /*/noexist " "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
#
# ls commands.
#
smbclient_expect_error "ls" " $name " "" "NT_STATUS_OK" || return 1
2023-10-18 11:50:20 +02:00
smbclient_expect_error "ls" " $name /noexist " "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "ls" " $name /* " "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
2022-04-22 15:34:11 +02:00
smbclient_expect_error "ls" " $name /*/noexist " "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
# Now in subdirectory emptydir
smbclient_expect_error "ls" " emptydir/ $name " "" "NT_STATUS_OK" || return 1
2023-10-18 11:50:20 +02:00
smbclient_expect_error "ls" " emptydir/ $name /noexist " "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "ls" " emptydir/ $name /* " "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
2022-04-22 15:34:11 +02:00
smbclient_expect_error "ls" " emptydir/ $name /*/noexist " "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
#
# SMB1+POSIX stat commands. All symlinks can be stat'ed.
#
smbclient_expect_error "stat" " $name " "" "NT_STATUS_OK" || return 1
smbclient_expect_error "stat" " emptydir/ $name " "" "NT_STATUS_OK" || return 1
#
# del commands. Under SMB1+POSIX we can legitimately delete symlinks, so don't
# try and delete symlink targets, we need them for the later tests.
#
2023-10-18 11:50:20 +02:00
smbclient_expect_error "del" " $name /noexist " "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
2022-04-22 15:34:11 +02:00
# Now in subdirectory emptydir
2023-10-18 11:50:20 +02:00
smbclient_expect_error "del" " emptydir/ $name /noexist " "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
2021-12-07 12:34:38 -08:00
2022-04-22 15:34:11 +02:00
if [ " $do_rename " = "do rename" ] ; then
#
# rename commands. Under SMB1+POSIX we can legitimately rename symlinks, so don't
# try and rename symlink targets, we need them for the later tests.
#
2021-12-07 12:34:38 -08:00
smbclient_expect_error "rename" "file_exists" " $name /noexist " "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
2022-04-22 15:34:11 +02:00
# Now in subdirectory emptydir
2021-12-07 12:34:38 -08:00
smbclient_expect_error "rename" "file_exists" " emptydir/ $name /noexist " "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
2022-04-22 15:34:11 +02:00
fi
return 0
2021-12-07 12:34:38 -08:00
}
#
# Check error code returns traversing through different
# kinds of symlinks over SMB1+posix.
#
test_symlink_traversal_SMB1_posix( )
{
test_symlink_traversal_SMB1_posix_onename "symlink_noexist" "no rename" || return 1
test_symlink_traversal_SMB1_posix_onename "symlink_file_outside_share" "do rename" || return 1
test_symlink_traversal_SMB1_posix_onename "symlink_dir_outside_share" "do rename" || return 1
test_symlink_traversal_SMB1_posix_onename "symlink_dir_outside_share_noexist" "no rename" || return 1
test_symlink_traversal_SMB1_posix_onename "symlink_file_outside_share_noperms" "do rename" || return 1
test_symlink_traversal_SMB1_posix_onename "symlink_dir_outside_share_noperms" "do rename" || return 1
2022-04-22 15:34:11 +02:00
#
# Test paths within share with no permissions.
#
# Can't 'get' file with no perms.
2021-12-07 12:34:38 -08:00
smbclient_expect_error "get" "file_inside_share_noperms" "" "NT_STATUS_ACCESS_DENIED" || return 1
2022-04-22 15:34:11 +02:00
# In SMB1+POSIX you can't "get" a symlink at all.
2021-12-07 12:34:38 -08:00
smbclient_expect_error "get" "symlink_file_inside_share_noperms" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
2022-04-22 15:34:11 +02:00
# But can list it and the symlink to it.
2021-12-07 12:34:38 -08:00
smbclient_expect_error "ls" "file_inside_share_noperms" "" "NT_STATUS_OK" || return 1
smbclient_expect_error "ls" "symlink_file_inside_share_noperms" "" "NT_STATUS_OK" || return 1
2022-04-22 15:34:11 +02:00
# Can't 'get' file inside a directory with no perms.
2021-12-07 12:34:38 -08:00
smbclient_expect_error "get" "dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1
2022-04-22 15:34:11 +02:00
# In SMB1+POSIX you can't traverse through a symlink that points to a noperm directory.
2022-08-04 11:32:05 -07:00
smbclient_expect_error "get" "symlink_dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1
2022-04-22 15:34:11 +02:00
# But can list the directory with no perms and the symlink to it.
2021-12-07 12:34:38 -08:00
smbclient_expect_error "ls" "dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1
smbclient_expect_error "ls" "symlink_dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1
}
testit "symlink_traversal_SMB1_posix" \
2022-04-22 15:34:11 +02:00
test_symlink_traversal_SMB1_posix ||
failed = $(( failed + 1 ))
2021-12-07 12:34:38 -08:00
#
# Cleanup.
do_cleanup
testok " $0 " " $failed "