diff options
Diffstat (limited to 'tests/drop-privileges')
-rw-r--r-- | tests/drop-privileges | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/tests/drop-privileges b/tests/drop-privileges new file mode 100644 index 0000000..0596e31 --- /dev/null +++ b/tests/drop-privileges @@ -0,0 +1,166 @@ +# Check privilige drop: UID/GID changes, chdir, environment, and file +# descriptors + +# create wrapper to inspect processes +STATUSDIR="/dev/shm/lacme-wrap" +install -oroot -groot -m0755 /dev/stdin /run/lacme-wrap <<-EOF + #!/bin/sh + set -ue + PATH="/usr/bin:/bin" + export PATH + + prefix="$STATUSDIR/\${1##*[/-]}" + cat </proc/\$\$/status >"\$prefix/status" + pwd >"\$prefix/cwd" + stat -c "%U:%G %#a" . >"\$prefix/cwd-mod" + sort -z </proc/\$\$/environ | tr "\\0" "\\n" >"\$prefix/environ" + ( find -P /proc/\$\$/fd -mindepth 1 \! -lname "\$0" -printf "%P %#m %U:%G %l\\n" >"\$prefix/fd" ) + + exec "\$@" +EOF + +# also check privilege drop for the spawned accountd +adduser --system --group \ + --home /nonexistent --no-create-home \ + --gecos "lacme account user" \ + --quiet lacme-account +sed -ri 's|^#user\s*=\s*$|user = lacme-account|' /etc/lacme/lacme.conf +sed -ri 's|^#group\s*=\s*$|group = lacme-account|' /etc/lacme/lacme.conf +chown lacme-account: /etc/lacme/account.key + +install -oroot -groot -dm0755 -- "$STATUSDIR" +install -olacme-account -groot -dm0700 -- "$STATUSDIR/accountd" +install -o_lacme-client -groot -dm0700 -- "$STATUSDIR/client" +install -o_lacme-www -groot -dm0700 -- "$STATUSDIR/webserver" + +# test with a group that's not the primary group (nogroup) of _lacme-www etc +addgroup --system nogroup2 +sed -ri 's|^#?group\s*=\s*nogroup$|group = nogroup2|' /etc/lacme/lacme.conf +sed -ri 's|^#?command\s*=.*/lacme-accountd$|command = /run/lacme-wrap /usr/bin/lacme-accountd|' /etc/lacme/lacme.conf +sed -ri 's|^#?command\s*=.*/lacme/client$|command = /run/lacme-wrap /usr/libexec/lacme/client|' /etc/lacme/lacme.conf +sed -ri 's|^#?command\s*=.*/lacme/webserver$|command = /run/lacme-wrap /usr/libexec/lacme/webserver|' /etc/lacme/lacme.conf +sed -ri 's|^#?config\s*=\s*$|config = /etc/lacme/lacme-accountd.conf|' /etc/lacme/lacme.conf + +check_status() { + local path="$STATUSDIR/$1/status" user="$2" group="$3" + UID="$(getent passwd "$user" | cut -sd: -f3)" + GID="$(getent group "$group" | cut -sd: -f3)" + [ -n "$UID" -a -n "$GID" ] || return 1 + grep -Ex "Uid:\\s+$UID\\s+$UID\\s+$UID\\s+$UID" "$path" || return 1 + grep -Ex "Gid:\\s+$GID\\s+$GID\\s+$GID\\s+$GID" "$path" || return 1 + grep -Ex "Groups:\s+$GID\s*" "$path" || return 1 +} +check_cwd() { + local path="$STATUSDIR/$1/cwd" dir="$2" cwd + cwd="$(cat <"$path")" || return 1 + [ "$cwd" = "$dir" ] || return 1 +} + +check_accountd() { + local socket_ino stderr prefix="$STATUSDIR/accountd" + check_status accountd lacme-account lacme-account || return 1 + check_cwd accountd / || return 1 + + diff --label="a/accountd/environ" --label="b/accountd/environ" \ + --color=auto --unified "$prefix/environ" - <<-EOF + HOME=/nonexistent + LOGNAME=lacme-account + PATH=/usr/bin:/bin + SHELL=/usr/sbin/nologin + TERM=$TERM + USER=lacme-account + EOF + + stderr="$(readlink -e "/proc/$$/fd/2")" + socket_ino="$(sed -rn '/^0 .* socket:\[([0-9]+)\]$/ {s//\1/p;q}' "$prefix/fd")" + [ -n "$socket_ino" ] || return 1 + grep -Fxq "0 0700 $UID:$GID socket:[$socket_ino]" "$prefix/fd" || return 1 + grep -Fxq "1 0700 $UID:$GID socket:[$socket_ino]" "$prefix/fd" || return 1 + grep -Fxq "2 0700 $UID:$GID $stderr" "$prefix/fd" || return 1 + sed -ri '\#^[012] #d' "$prefix/fd" + ! test -s "$prefix/fd" || return 1 +} +check_client() { + local command="$1" cwd="$2" UID GID stdout stderr prefix="$STATUSDIR/client" + check_status client _lacme-client nogroup2 + check_cwd client "$cwd" + + diff --label="a/client/environ" --label="b/client/environ" \ + --color=auto --unified "$prefix/environ" - <<-EOF + DEBUG=0 + HOME=/nonexistent + LOGNAME=_lacme-client + PATH=/usr/bin:/bin + SHELL=/usr/sbin/nologin + TERM=$TERM + USER=_lacme-client + EOF + + stdout="$(readlink -e "/proc/$$/fd/1")" + stderr="$(readlink -e "/proc/$$/fd/2")" + if [ "$command" = "account" ]; then # no pipe + grep -Fxq "0 0500 $UID:$GID /dev/null" "$prefix/fd" || return 1 + grep -Fxq "1 0700 $UID:$GID $stdout" "$prefix/fd" || return 1 + elif [ "$command" = "order" ]; then + grep -Exq "0 0500 $UID:$GID pipe:\[[0-9]+\]" "$prefix/fd" || return 1 + grep -Exq "1 0300 $UID:$GID pipe:\[[0-9]+\]" "$prefix/fd" || return 1 + else + exit 1 + fi + grep -Fxq "2 0700 $UID:$GID $stderr" "$prefix/fd" || return 1 + sed -ri '\#^[012] #d' "$prefix/fd" + + grep -Exq "[0-9]+ 0700 $UID:$GID socket:\[[0-9]+\]" "$prefix/fd" || return 1 + sed -ri '0,\#^[0-9]+ .* socket:\[[0-9]+\]$# {//d}' "$prefix/fd" + + grep -Exq "[0-9]+ 0500 $UID:$GID /etc/lacme/lacme\.conf" "$prefix/fd" || return 1 + sed -ri '0,\#^[0-9]+ .* /etc/lacme/lacme\.conf$# {//d}' "$prefix/fd" + ! test -s "$prefix/fd" || return 1 +} +check_webserver() { + local cwd="$1" UID GID stdout stderr prefix="$STATUSDIR/webserver" + check_status webserver _lacme-www nogroup2 + check_cwd webserver "$cwd" + + diff --label="a/webserver/environ" --label="b/webserver/environ" \ + --color=auto --unified "$prefix/environ" - <<-EOF + DEBUG=0 + HOME=/nonexistent + LOGNAME=_lacme-www + PATH=/usr/bin:/bin + SHELL=/usr/sbin/nologin + TERM=$TERM + USER=_lacme-www + EOF + + stdout="$(readlink -e "/proc/$$/fd/1")" + stderr="$(readlink -e "/proc/$$/fd/2")" + grep -Fxq "0 0500 $UID:$GID /dev/null" "$prefix/fd" || return 1 + grep -Fxq "1 0700 $UID:$GID $stdout" "$prefix/fd" || return 1 + grep -Fxq "2 0700 $UID:$GID $stderr" "$prefix/fd" || return 1 + sed -ri '\#^[012] #d' "$prefix/fd" + + grep -Exq "[0-9]+ 0700 $UID:$GID socket:\[[0-9]+\]" "$prefix/fd" || return 1 + sed -ri '0,\#^[0-9]+ .* socket:\[[0-9]+\]$# {//d}' "$prefix/fd" + ! test -s "$prefix/fd" || return 1 +} + +lacme account +check_accountd +check_client account / +! test -e "$STATUSDIR/webserver/status" # account 'command' doesn't start the webserver + +lacme newOrder +check_accountd +challenge_dir="$(cat "$STATUSDIR/webserver/cwd")" +[ "${challenge_dir#"/tmp/acme-challenge."}" != "$challenge_dir" ] || exit 1 +check_client order "$challenge_dir" +check_webserver "$challenge_dir" + +# the temporary challenge directory is created with permissive mode +diff --label="a/webserver/cwd" --label="b/webserver/cwd" \ + --color=auto --unified "$STATUSDIR/webserver/cwd-mod" - <<-EOF + _lacme-client:root 0755 +EOF + +# vim: set filetype=sh : |