#!/bin/bash

# This script demonstrates a quirk in SVN's authz path-based access control
# where it fails to recognise square brackets in the file name.
#
# This script will:
#   - Create a test SVN repository in a temporary directory (in the current
#     working directory)
#   - Write the appropriate configuration files
#   - Run svnserve to deploy the repository
#   - Make a checkout to another temporary directory and commit two new files
#   - Attempt to access those files using an account that shouldn't be able to
#
# The output at the end should indicate that "test_user2" can't access BOTH
# files.s
#
# This script does NOT clean up after itself, in case further debugging is
# required. It also makes no attempt to detect and work around existing svnserve
# processes!

REPO_NAME=testrepo
REPO_AREA=$(mktemp -d "svnrepo-XXXXXX")
SVN_REPO="${REPO_AREA}/${REPO_NAME}"

SVNSERVE_PID="svnserve-pid"

# File names and their URL escaped equivalents
FILENAME_GOOD="test 1.txt"
FILENAME_GOOD_ESC="test%201.txt"
FILENAME_BAD="[12345] test 2.txt"
FILENAME_BAD_ESC="%5B12345%5D%20test%202.txt"

# Create the repository
svnadmin create "${SVN_REPO}"

# Create the accounts
cat <<EOF >"${SVN_REPO}/conf/passwd"
[users]
test_user1 = test_pass1
test_user2 = test_pass2

EOF

# Create the config file
cat <<EOF >"${SVN_REPO}/conf/svnserve.conf"
[general]
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz
realm = Test Repo
EOF

# Create the authz file
cat <<EOF >"${SVN_REPO}/conf/authz"
[${REPO_NAME}:/]
test_user1=rw
test_user2=rw

[${REPO_NAME}:/${FILENAME_GOOD}]
test_user2=

[${REPO_NAME}:/${FILENAME_BAD}]
test_user2=
EOF

# Start the SVN server
svnserve -d -r "${REPO_AREA}" \
    --pid-file="${SVNSERVE_PID}"

if [ $? -ne 0 ]; then
    echo "Could not start svnserve"
    exit 1
fi

echo "svnserve PID is $(cat ${SVNSERVE_PID})"

# Create checkout
SVN_TEST_AREA=$(mktemp -d "svntemp-XXXXXX")
svn --non-interactive --no-auth-cache \
    --username test_user1 \
    --password test_pass1 \
    checkout "svn://localhost/${REPO_NAME}" "${SVN_TEST_AREA}"
   
# Create the files
echo "Test file good" > "${SVN_TEST_AREA}/${FILENAME_GOOD}"
echo "Test file bad" > "${SVN_TEST_AREA}/${FILENAME_BAD}"

# Add the files
svn add "${SVN_TEST_AREA}/${FILENAME_GOOD}"
svn add "${SVN_TEST_AREA}/${FILENAME_BAD}"

# Commit the files
svn --non-interactive --no-auth-cache \
    --username test_user1 \
    --password test_pass1 \
    -m "Test commit" \
    commit "${SVN_TEST_AREA}"

# Test operation to see if we can access something we shouldn't
svn --non-interactive --no-auth-cache \
    --username test_user2 \
    --password test_pass2 \
    info "svn://localhost/${REPO_NAME}/${FILENAME_GOOD_ESC}" > /dev/null 2>&1

if [ $? -eq 0 ]; then
    echo "  * test_user2 can access \"${FILENAME_GOOD}\""
else
    echo "  * test_user2 can't access \"${FILENAME_GOOD}\""
fi

# Test operation to see if we can access something we shouldn't
svn --non-interactive --no-auth-cache \
    --username test_user2 \
    --password test_pass2 \
    info "svn://localhost/${REPO_NAME}/${FILENAME_BAD_ESC}" > /dev/null 2>&1

if [ $? -eq 0 ]; then
    echo "  * test_user2 can access \"${FILENAME_BAD}\""
else
    echo "  * test_user2 can't access \"${FILENAME_BAD}\""
fi