48 lines
2 KiB
Bash
48 lines
2 KiB
Bash
#!/bin/sh
|
|
# Restore only known group-write additions on unchanged, owned hook inodes.
|
|
set +vx
|
|
set -eu
|
|
export PATH=/usr/bin:/bin
|
|
records=$1
|
|
test "$(id -u)" = 1000
|
|
fail() { printf '{"mode_check":"%s","result":"refused"}\n' "$1"; exit 61; }
|
|
tab=$(printf '\t')
|
|
validate() {
|
|
mode=$1 sum=$2 path=$3
|
|
case "$mode" in 755|775) ;; *) fail unsupported-baseline-mode;; esac
|
|
case "$path" in /data/git/gitea-repositories/*/*.git/hooks/*) ;; *) fail path-scope;; esac
|
|
parent=${path%/*}
|
|
while test "$parent" != /data; do
|
|
test -d "$parent" && test ! -L "$parent" || fail parent-shape
|
|
parent=${parent%/*}
|
|
done
|
|
test -f "$path" && test ! -L "$path" || fail file-shape
|
|
test "$(stat -c %u "$path")" = 1000 && test "$(stat -c %g "$path")" = 1000 || fail file-owner
|
|
test "$(sha256sum "$path" | cut -d ' ' -f 1)" = "$sum" || fail file-hash
|
|
current=$(stat -c %a "$path")
|
|
test "$current" = "$mode" || { test "$mode" = 755 && test "$current" = 775; } || fail unexpected-mode
|
|
}
|
|
count=0
|
|
while IFS="$tab" read -r mode sum path; do validate "$mode" "$sum" "$path"; count=$((count+1)); done < "$records"
|
|
test "$count" -gt 0 || fail empty-scope
|
|
changed=0
|
|
while IFS="$tab" read -r mode sum path; do
|
|
validate "$mode" "$sum" "$path"
|
|
if test "$current" != "$mode"; then
|
|
inode=$(stat -c '%d:%i' "$path")
|
|
exec 7< "$path"
|
|
fd=/proc/self/fd/7
|
|
test "$(stat -L -c '%d:%i' "$fd")" = "$inode" || fail opened-inode
|
|
test "$(stat -L -c %u "$fd")" = 1000 && test "$(stat -L -c %g "$fd")" = 1000 || fail opened-owner
|
|
test "$(stat -L -c %a "$fd")" = 775 || fail opened-mode
|
|
test "$(sha256sum "$fd" | cut -d ' ' -f 1)" = "$sum" || fail opened-hash
|
|
chmod "$mode" "$fd"
|
|
test "$(stat -L -c %a "$fd")" = "$mode" || fail restored-mode
|
|
test -f "$path" && test ! -L "$path" && test "$(stat -c '%d:%i' "$path")" = "$inode" || fail final-inode
|
|
exec 7<&-
|
|
changed=$((changed+1))
|
|
fi
|
|
validate "$mode" "$sum" "$path"
|
|
test "$current" = "$mode" || fail final-mode
|
|
done < "$records"
|
|
printf '{"hook_modes_verified":%s,"group_write_additions_reversed":%s}\n' "$count" "$changed"
|