smbd: Fix a typo in a few places
[samba.git] / source3 / script / tests / test_symlink_traversal_smb1.sh
1 #!/bin/sh
2
3 if [ $# -lt 7 ]; then
4         cat <<EOF
5 Usage: test_symlink_traversal_smb1.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT
6 EOF
7         exit 1
8 fi
9
10 SERVER="${1}"
11 SERVER_IP="${2}"
12 USERNAME="${3}"
13 PASSWORD="${4}"
14 LOCAL_PATH="${5}"
15 PREFIX="${6}"
16 SMBCLIENT="${7}"
17 SMBCLIENT="$VALGRIND ${SMBCLIENT}"
18 shift 6
19
20 incdir=$(dirname "$0")/../../../testprogs/blackbox
21 . "$incdir"/subunit.sh
22
23 failed=0
24
25 # Do not let deprecated option warnings muck this up
26 SAMBA_DEPRECATED_SUPPRESS=1
27 export SAMBA_DEPRECATED_SUPPRESS
28
29 # Define the test environment/filenames.
30 #
31 share_test_dir="$LOCAL_PATH"
32 #
33 # These files/directories will be created.
34 #
35 file_outside_share="/tmp/symlink_traverse_test_file.$$"
36 dir_outside_share="/tmp/symlink_traverse_test_dir.$$"
37 file_outside_share_noperms="/tmp/symlink_traverse_test_file_noperm.$$"
38 dir_outside_share_noperms="/tmp/symlink_traverse_test_dir_noperm.$$"
39 #
40 # These two objects do not exist.
41 #
42 file_outside_share_noexist="/tmp/symlink_traverse_test_noexist.$$"
43 dir_outside_share_noexist="/tmp/symlink_traverse_test_dir_noexist.$$"
44
45 #
46 # Cleanup function.
47 #
48 do_cleanup()
49 {
50         (
51                 #subshell.
52                 cd "$share_test_dir" || return
53                 rm -f "file_exists"
54                 rm -f "symlink_noexist"
55                 rm -f "symlink_file_outside_share"
56                 rm -f "symlink_file_outside_share_noexist"
57                 rm -f "symlink_dir_outside_share"
58                 rm -f "symlink_dir_outside_share_noexist"
59                 rm -f "symlink_file_outside_share_noperms"
60                 rm -f "symlink_dir_outside_share_noperms"
61                 rm -rf "emptydir"
62                 # Links inside share.
63                 rm -f "symlink_file_inside_share_noperms"
64                 rm -f "file_inside_share_noperms"
65                 rm -f "symlink_dir_inside_share_noperms"
66                 chmod 755 "dir_inside_share_noperms"
67                 rm -rf "dir_inside_share_noperms"
68         )
69         rm -f "$file_outside_share"
70         rm -rf "$dir_outside_share"
71         rm -f "$file_outside_share_noperms"
72         rm -rf "$dir_outside_share_noperms"
73 }
74
75 #
76 # Ensure we start from a clean slate.
77 #
78 do_cleanup
79
80 #
81 # Create the test files/directories/symlinks.
82 #
83 # File/directory explicitly outside share.
84 touch "$file_outside_share"
85 mkdir "$dir_outside_share"
86 # File/directory explicitly outside share with permission denied.
87 touch "$file_outside_share_noperms"
88 chmod 0 "$file_outside_share_noperms"
89 mkdir "$dir_outside_share_noperms"
90 chmod 0 "$dir_outside_share_noperms"
91 #
92 # Create links to these objects inside the share definition.
93 (
94         #subshell.
95         cd "$share_test_dir" || return
96         touch "file_exists"
97         ln -s "noexist" "symlink_noexist"
98         ln -s "$file_outside_share" "symlink_file_outside_share"
99         ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist"
100         ln -s "$dir_outside_share" "symlink_dir_outside_share"
101         ln -s "$dir_outside_share_noexist" "symlink_dir_outside_share_noexist"
102         ln -s "$file_outside_share_noperms" "symlink_file_outside_share_noperms"
103         ln -s "$dir_outside_share_noperms" "symlink_dir_outside_share_noperms"
104         #
105         # Create the identical symlink set underneath "emptydir"
106         mkdir "emptydir"
107         (
108                 #subshell
109                 cd "emptydir" || return
110                 touch "file_exists"
111                 ln -s "noexist" "symlink_noexist"
112                 ln -s "$file_outside_share" "symlink_file_outside_share"
113                 ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist"
114                 ln -s "$dir_outside_share" "symlink_dir_outside_share"
115                 ln -s "$dir_outside_share_noexist" "symlink_dir_outside_share_noexist"
116                 ln -s "$file_outside_share_noperms" "symlink_file_outside_share_noperms"
117                 ln -s "$dir_outside_share_noperms" "symlink_dir_outside_share_noperms"
118         )
119         #
120         # Create symlinks to access denied file and directory
121         # objects within the share
122         touch "file_inside_share_noperms"
123         chmod 0 "file_inside_share_noperms"
124         ln -s "file_inside_share_noperms" "symlink_file_inside_share_noperms"
125         mkdir "dir_inside_share_noperms"
126         touch "dir_inside_share_noperms/noperm_file_exists"
127         chmod 0 "dir_inside_share_noperms"
128         ln -s "dir_inside_share_noperms" "symlink_dir_inside_share_noperms"
129 )
130
131 #
132 # smbclient function given command, path, expected error, and posix.
133 #
134 smbclient_expect_error()
135 {
136         filecmd="$1"
137         filename1="$2"
138         filename2="$3"
139         expected_error="$4"
140         tmpfile=$PREFIX/smbclient_interactive_prompt_commands
141         cat >"$tmpfile" <<EOF
142 $filecmd $filename1 $filename2
143 quit
144 EOF
145         cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I$SERVER_IP -mNT1 < $tmpfile 2>&1'
146         eval echo "$cmd"
147         out=$(eval "$cmd")
148         ret=$?
149         rm -f "$tmpfile"
150
151         if [ $ret != 0 ]; then
152                 printf "%s\n" "$out"
153                 printf "failed accessing local_symlinks with error %s\n" "$ret"
154                 return 1
155         fi
156
157         if [ "$expected_error" = "NT_STATUS_OK" ]; then
158                 printf "%s" "$out" | grep -v "NT_STATUS_"
159         else
160                 printf "%s" "$out" | grep "$expected_error"
161         fi
162         ret=$?
163         if [ $ret != 0 ]; then
164                 printf "%s\n" "$out"
165                 printf "failed - should get %s doing \"%s %s %s\"\n" "$expected_error" "$filecmd" "$filename1" "$filename2"
166                 return 1
167         fi
168 }
169
170 #
171 # SMB1 tests.
172 #
173 test_symlink_traversal_SMB1_onename()
174 {
175         name="$1"
176         do_rename="$2"
177         #
178         # get commands.
179         #
180         smbclient_expect_error "get" "$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
181         smbclient_expect_error "get" "$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
182         smbclient_expect_error "get" "$name/*" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
183         smbclient_expect_error "get" "$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
184         # Now in subdirectory emptydir
185         smbclient_expect_error "get" "emptydir/$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
186         smbclient_expect_error "get" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
187         smbclient_expect_error "get" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
188         smbclient_expect_error "get" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
189         #
190         # ls commands.
191         #
192         smbclient_expect_error "ls" "$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1
193         smbclient_expect_error "ls" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
194         smbclient_expect_error "ls" "$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
195         smbclient_expect_error "ls" "$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
196         # Now in subdirectory emptydir
197         smbclient_expect_error "ls" "emptydir/$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1
198         smbclient_expect_error "ls" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
199         smbclient_expect_error "ls" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
200         smbclient_expect_error "ls" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
201
202         #
203         # del commands.
204         # smbclient internally does a cli_list, so we expect similar errors.
205         #
206         smbclient_expect_error "del" "$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1
207         smbclient_expect_error "del" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
208         # Now in subdirectory emptydir
209         smbclient_expect_error "del" "emptydir/$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1
210         smbclient_expect_error "del" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
211
212         if [ "$do_rename" = "do rename" ]; then
213                 #
214                 # rename commands.
215                 #
216                 smbclient_expect_error "rename" "file_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
217                 smbclient_expect_error "rename" "file_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
218                 # Now in subdirectory emptydir
219                 smbclient_expect_error "rename" "file_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
220                 smbclient_expect_error "rename" "file_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
221         fi
222         return 0
223 }
224
225 #
226 # Check error code returns traversing through different
227 # kinds of symlinks over SMB1.
228 #
229 test_symlink_traversal_SMB1()
230 {
231         test_symlink_traversal_SMB1_onename "symlink_noexist" "no rename" || return 1
232         test_symlink_traversal_SMB1_onename "symlink_file_outside_share" "do rename" || return 1
233         test_symlink_traversal_SMB1_onename "symlink_dir_outside_share" "do rename" || return 1
234         test_symlink_traversal_SMB1_onename "symlink_dir_outside_share_noexist" "no rename" || return 1
235         test_symlink_traversal_SMB1_onename "symlink_file_outside_share_noperms" "do rename" || return 1
236         test_symlink_traversal_SMB1_onename "symlink_dir_outside_share_noperms" "do rename" || return 1
237         #
238         # Test paths within share with no permissions.
239         #
240         # Can't 'get' file with no perms or a symlink to it.
241         smbclient_expect_error "get" "file_inside_share_noperms" "" "NT_STATUS_ACCESS_DENIED" || return 1
242         smbclient_expect_error "get" "symlink_file_inside_share_noperms" "" "NT_STATUS_ACCESS_DENIED" || return 1
243         # But can list it and the symlink to it.
244         smbclient_expect_error "ls" "file_inside_share_noperms" "" "NT_STATUS_OK" || return 1
245         smbclient_expect_error "ls" "symlink_file_inside_share_noperms" "" "NT_STATUS_OK" || return 1
246         # Can't 'get' file inside a directory with no perms or a symlink to it.
247         smbclient_expect_error "get" "dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1
248         smbclient_expect_error "get" "symlink_dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1
249         # But can list the directory with no perms and the symlink to it.
250         smbclient_expect_error "ls" "dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1
251         smbclient_expect_error "ls" "symlink_dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1
252 }
253
254 testit "symlink_traversal_SMB1" \
255         test_symlink_traversal_SMB1 ||
256         failed=$((failed + 1))
257
258 #
259 # Cleanup.
260 do_cleanup
261
262 testok "$0" "$failed"