server.sh (2531B)
- #!/bin/sh
- # shellcheck disable=SC1017
- # Copyright 2020-2021 Haelwenn (lanodan) Monnier <contact+gemini@hacktivis.me>
- # Distributed under the terms of the GNU Affero General Public License version 3
- # AGPL-3 because it's a service on the internet, screw permissive licences for these
- # Notes:
- # - URLs are barely parsed and mostly taken as-is, which could be dangerous
- # - Recognised hostnames are directories in $GEMDIR, they must also have a $host:1965 symlink
- # - stunnel chroot ability is untested for now
- # - Lastest known version of the specification: v0.14.3, November 29th 2020
- export GEMDIR="/srv/gemini"
- bubblewrap() {
- bwrap \
- --unshare-user --uid 65534 --gid 65534 \
- --unshare-ipc --unshare-pid --unshare-uts --unshare-cgroup-try \
- --ro-bind /bin /bin \
- --ro-bind /lib /lib \
- --ro-bind /lib64 /lib64 \
- --ro-bind /usr /usr \
- --ro-bind /git /git \
- --ro-bind /etc /etc \
- --ro-bind "${GEMDIR}" "${GEMDIR}" \
- --chdir "${GEMDIR}" \
- --proc /proc \
- --dev /dev \
- --die-with-parent \
- "$@"
- }
- IFS=#'
- ' read -r line
- # ' hack for vis editor to reset hightlighting…
- query="${line#gemini://}"
- query="${query%%../*}"
- query="${query//%20/ }"
- path="$GEMDIR/${query//\?*}"
- status="--"
- if echo "$path" | grep -Eq '.gmi$'
- then
- mime="text/gemini; charset=utf-8"
- else
- mime=$(file --mime -b "$path" 2>/dev/null)
- fi
- if [ -r "$path" -a -f "$path" ]
- then
- if echo "$query" | grep -Eq '/cgi-bin/'
- then
- if [ -x "$path" -a -f "$path" ]
- then
- if echo "$query" | grep -Eq '\?'
- then
- bubblewrap "./${query//\?*}" "${query//*\?}"
- else
- bubblewrap "./${query//\?*}" ""
- fi
- status="x$?"
- else
- status="50"
- printf '50 File not executable or non-existent\r\n'
- fi
- else
- status="20"
- printf '20 %s\r\n' "$mime"
- cat "$path" 2>/dev/null
- fi
- elif [ -r "$path" -a -d "$path" ]
- then
- if echo "$path" | grep -Eq '/$'
- then
- if [ -r "$path/index.gmi" -a -f "$path/index.gmi" ]
- then
- status="20"
- printf '20 text/gemini; charset=utf-8\r\n'
- cat "$path/index.gmi" 2>/dev/null
- else
- status="20"
- printf '20 text/gemini; charset=utf-8\r\n'
- printf '# Index of %s\n' "$query"
- cd "$path" && find . -mindepth 1 -maxdepth 1 | sed -e 's; ;%20;g' -e "s;^\./;=> ;" 2>/dev/null
- fi
- else
- status="30"
- printf '30 gemini://%s/\r\n' "$query"
- fi
- else
- status="50"
- printf '50 File not readable or non-existent\r\n'
- fi
- # I know… blame France data rentention policy
- logger -p local0.notice "${REMOTE_HOST:-?host?} ${REMOTE_PORT:-?port?} ${line} ${status}" 2>/dev/null 1>/dev/null