list.sh (7603B)
1 #!/bin/sh 2 3 set -eu 4 5 . "$(dirname "$0")/testlib.sh" 6 7 CGI=${1:-build/list.cgi} 8 9 list() { 10 env \ 11 STORAGE_ROOT="$TESTROOT/storage" \ 12 SIMPLEFILES_ROOT=./html \ 13 REMOTE_USER=alice \ 14 REQUEST_METHOD=GET \ 15 "$CGI" 16 } 17 18 list_repo() { 19 env \ 20 STORAGE_ROOT="$TESTROOT/storage" \ 21 SIMPLEFILES_ROOT=./html \ 22 SCRIPT_NAME="/$1/list.cgi" \ 23 REMOTE_USER=alice \ 24 REQUEST_METHOD=GET \ 25 "$CGI" 26 } 27 28 list_user() { 29 user=$1 30 31 env \ 32 SCRIPT_NAME=/default/list.cgi \ 33 STORAGE_ROOT="$TESTROOT/storage" \ 34 SIMPLEFILES_ROOT=./html \ 35 REQUEST_METHOD=GET \ 36 REMOTE_USER="$user" \ 37 "$CGI" 38 } 39 40 list_no_user() { 41 ( 42 unset REMOTE_USER 43 44 export SCRIPT_NAME=/default/list.cgi 45 export SIMPLEFILES_ROOT=./html 46 export SIMPLEFILES_CONFIG="$TEST_CONFIG" 47 export STORAGE_ROOT="$TESTROOT/storage" 48 export REQUEST_METHOD=GET 49 50 "$CGI" 51 ) 52 } 53 54 list_no_user_root() { 55 root=$1 56 57 ( 58 unset REMOTE_USER 59 60 export SCRIPT_NAME=/default/list.cgi 61 export SIMPLEFILES_ROOT="$root" 62 export SIMPLEFILES_CONFIG="$TEST_CONFIG" 63 export STORAGE_ROOT="$TESTROOT/storage" 64 export REQUEST_METHOD=GET 65 66 "$CGI" 67 ) 68 } 69 70 ############################################################################## 71 72 reset_testroot 73 74 check_body \ 75 "empty page" \ 76 "SimpleFiles" \ 77 list 78 79 check_body \ 80 "table header" \ 81 "<th>Name</th>" \ 82 list 83 84 ############################################################################## 85 86 printf 'dummy\n' > "$TESTROOT/storage/default/file1.txt" 87 88 check_body \ 89 "one filename" \ 90 "file1.txt" \ 91 list 92 93 ############################################################################## 94 95 printf 'dummy\n' > "$TESTROOT/storage/default/file2.txt" 96 97 check_body \ 98 "second filename" \ 99 "file2.txt" \ 100 list 101 102 ############################################################################## 103 104 mkdir "$TESTROOT/storage/default/subdir" 105 106 check_not_body \ 107 "ignore directories" \ 108 "subdir" \ 109 list 110 111 ############################################################################## 112 113 mkdir -p "$TESTROOT/storage/music" 114 mkdir -p "$TESTROOT/storage/poetry" 115 116 printf 'music\n' > "$TESTROOT/storage/music/song.mp3" 117 printf 'poetry\n' > "$TESTROOT/storage/poetry/poem.txt" 118 119 check_body \ 120 "music repository" \ 121 "song.mp3" \ 122 list_repo music 123 124 check_not_body \ 125 "music excludes poetry" \ 126 "poem.txt" \ 127 list_repo music 128 129 check_body \ 130 "poetry repository" \ 131 "poem.txt" \ 132 list_repo poetry 133 134 check_not_body \ 135 "poetry excludes music" \ 136 "song.mp3" \ 137 list_repo poetry 138 139 ############################################################################## 140 141 mkdir -p "$TESTROOT/secret" 142 143 printf 'secret\n' > "$TESTROOT/secret/password.txt" 144 145 check_not_body \ 146 "reject repository traversal" \ 147 "password.txt" \ 148 list_repo "../secret" 149 150 ############################################################################## 151 152 # Test HTML escaping of filenames 153 154 escaped_filename='<test>&file.txt' 155 raw_filename='<test>&file.txt' 156 157 printf 'dummy\n' > "$TESTROOT/storage/default/$raw_filename" 158 159 check_body \ 160 "escape filename in html" \ 161 "$escaped_filename" \ 162 list 163 164 check_body \ 165 "url encode filename" \ 166 "download.cgi?file=%3Ctest%3E%26file.txt" \ 167 list 168 169 ############################################################################## 170 171 printf 'QUOTA=1024\n' > "$TESTROOT/storage/default/.config" 172 173 check_not_body \ 174 "hide .config" \ 175 ".config" \ 176 list 177 178 ############################################################################## 179 # 180 # Read-only repository 181 # 182 183 reset_testroot 184 185 printf 'READ_ONLY=1\n' > "$TESTROOT/storage/default/.config" 186 printf 'hello\n' > "$TESTROOT/storage/default/file1.txt" 187 188 check_body \ 189 "readonly list still shows files" \ 190 "file1.txt" \ 191 list 192 193 check_not_body \ 194 "readonly list hides upload link" \ 195 "upload.cgi" \ 196 list 197 198 check_not_body \ 199 "readonly list hides delete link" \ 200 "delete.cgi" \ 201 list 202 203 #################################################### 204 # 205 # Authentication-aware access control 206 # 207 208 # 1 Anonymous access is rejected by default 209 210 reset_testroot 211 212 write_default_repo_config "" 213 214 printf '%s' 'list content' \ 215 > "$TESTROOT/storage/default/file.txt" 216 217 check_status \ 218 "anonymous listing rejected by default" \ 219 "403 Forbidden" \ 220 list_no_user 221 222 # 2 Anonymous listing is allowed when explicitly set 223 224 reset_testroot 225 226 write_default_repo_config "" 227 228 printf '%s' 'list content' \ 229 > "$TESTROOT/storage/default/file.txt" 230 231 write_global_config "ANONYMOUS_READ=1" 232 233 check_status \ 234 "anonymous listing allowed with ANONYMOUS_READ" \ 235 "200 OK" \ 236 list_no_user 237 238 check_body \ 239 "anonymous listing with ANONYMOUS_READ succeeds" \ 240 "file.txt" \ 241 list_no_user 242 243 check_not_body \ 244 "anonymous listing allowed hides upload link" \ 245 "upload.cgi" \ 246 list_no_user 247 248 check_not_body \ 249 "anonymous listing allowed hides delete link" \ 250 "delete.cgi?file=file.txt" \ 251 list_no_user 252 253 # 3 Authenticated non-admin listing remains allowed 254 255 reset_testroot 256 257 write_default_repo_config "" 258 259 printf '%s' 'list content' \ 260 > "$TESTROOT/storage/default/file.txt" 261 262 check_status \ 263 "authenticated listing allowed without ADMIN_USER" \ 264 "200 OK" \ 265 list_user \ 266 "alice" 267 268 check_body \ 269 "authenticated listing without ADMIN_USER succeeds" \ 270 "file.txt" \ 271 list_user \ 272 "alice" 273 274 check_not_body \ 275 "non-admin listing hides upload link" \ 276 "upload.cgi" \ 277 list_user \ 278 "alice" 279 280 check_not_body \ 281 "non-admin listing hides delete link" \ 282 "delete.cgi?file=file.txt" \ 283 list_user \ 284 "alice" 285 286 # 4 Matching admin user is allowed 287 288 reset_testroot 289 290 write_default_repo_config "ADMIN_USER=bob" 291 292 printf '%s' 'list content' \ 293 > "$TESTROOT/storage/default/file.txt" 294 295 check_status \ 296 "admin user allowed to list" \ 297 "200 OK" \ 298 list_user \ 299 "bob" 300 301 check_body \ 302 "admin listing succeeds" \ 303 "file.txt" \ 304 list_user \ 305 "bob" 306 307 check_body \ 308 "admin listing shows upload link" \ 309 "upload.cgi" \ 310 list_user \ 311 "bob" 312 313 check_body \ 314 "admin listing shows delete link" \ 315 "delete.cgi?file=file.txt" \ 316 list_user \ 317 "bob" 318 319 # 5 Non-admin authenticated user can read but cannot write 320 321 reset_testroot 322 323 write_default_repo_config "ADMIN_USER=bob" 324 325 printf '%s' 'list content' \ 326 > "$TESTROOT/storage/default/file.txt" 327 328 check_status \ 329 "non-admin user allowed to list" \ 330 "200 OK" \ 331 list_user \ 332 "alice" 333 334 check_body \ 335 "non-admin listing succeeds" \ 336 "file.txt" \ 337 list_user \ 338 "alice" 339 340 check_not_body \ 341 "non-admin listing hides upload link" \ 342 "upload.cgi" \ 343 list_user \ 344 "alice" 345 346 check_not_body \ 347 "non-admin listing hides delete link" \ 348 "delete.cgi?file=file.txt" \ 349 list_user \ 350 "alice" 351 352 # 6 ANONYMOUS_READ allows anonymous access even when ADMIN_USER is configured 353 354 reset_testroot 355 356 write_default_repo_config "ADMIN_USER=bob" 357 358 printf '%s' 'list content' \ 359 > "$TESTROOT/storage/default/file.txt" 360 361 write_global_config "ANONYMOUS_READ=1" 362 363 check_status \ 364 "anonymous listing allowed with ADMIN_USER and ANONYMOUS_READ" \ 365 "200 OK" \ 366 list_no_user 367 368 check_body \ 369 "anonymous listing succeeds with ADMIN_USER and ANONYMOUS_READ" \ 370 "file.txt" \ 371 list_no_user 372 373 check_not_body \ 374 "anonymous listing hides upload link" \ 375 "upload.cgi" \ 376 list_no_user 377 378 check_not_body \ 379 "anonymous listing hides delete link" \ 380 "delete.cgi?file=file.txt" \ 381 list_no_user 382 383 # 384 # Response generation 385 # 386 387 reset_testroot 388 389 write_default_repo_config "" 390 write_global_config "ANONYMOUS_READ=1" 391 392 printf 'hello\n' > "$TESTROOT/storage/default/file1.txt" 393 394 mkdir -p "$TESTROOT/html" 395 printf '{{UNKNOWN_VARIABLE}}' > "$TESTROOT/html/list.html" 396 397 check_status \ 398 "template failure returns 500" \ 399 "500 Internal Server Error" \ 400 list_no_user_root \ 401 "$TESTROOT/html" 402 403 test_result