aboutsummaryrefslogtreecommitdiffstats
path: root/tests/drop-privileges
diff options
context:
space:
mode:
Diffstat (limited to 'tests/drop-privileges')
-rw-r--r--tests/drop-privileges166
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 :