2048162057
Updater applies chmod/chown on config, spool and state paths on every run. SAC is the primary update path; optional cron uses the same behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
135 lines
3.9 KiB
Bash
135 lines
3.9 KiB
Bash
#!/bin/bash
|
|
# Path permission helpers for ssh-monitor, sac-client, watchdog, updater.
|
|
# shellcheck shell=bash
|
|
|
|
ssh_monitor_config_peek() {
|
|
local key="$1" file="$2" default="${3:-}"
|
|
local line val
|
|
[ -f "$file" ] || {
|
|
printf '%s\n' "$default"
|
|
return 0
|
|
}
|
|
line="$(grep -E "^[[:space:]]*${key}=" "$file" 2>/dev/null | tail -1)" || {
|
|
printf '%s\n' "$default"
|
|
return 0
|
|
}
|
|
val="${line#*=}"
|
|
val="${val#"${val%%[![:space:]]*}"}"
|
|
val="${val%"${val##*[![:space:]]}"}"
|
|
val="${val#\"}"
|
|
val="${val%\"}"
|
|
val="${val#\'}"
|
|
val="${val%\'}"
|
|
printf '%s\n' "$val"
|
|
}
|
|
|
|
ssh_monitor_truthy() {
|
|
case "${1,,}" in
|
|
1 | yes | true | on) return 0 ;;
|
|
esac
|
|
return 1
|
|
}
|
|
|
|
ssh_monitor_path_mode() {
|
|
local path="$1"
|
|
[ -e "$path" ] || return 1
|
|
stat -c '%a' "$path" 2>/dev/null || stat -f '%OLp' "$path" 2>/dev/null
|
|
}
|
|
|
|
ssh_monitor_path_owner() {
|
|
local path="$1"
|
|
[ -e "$path" ] || return 1
|
|
stat -c '%U:%G' "$path" 2>/dev/null
|
|
}
|
|
|
|
ssh_monitor_is_root_owned() {
|
|
local path="$1" own
|
|
[ -e "$path" ] || return 0
|
|
own="$(ssh_monitor_path_owner "$path" 2>/dev/null || true)"
|
|
[ "$own" = "root:root" ]
|
|
}
|
|
|
|
ssh_monitor_secure_dir() {
|
|
local dir="$1"
|
|
[ -n "$dir" ] || return 1
|
|
mkdir -p "$dir" 2>/dev/null || return 1
|
|
chmod 700 "$dir" 2>/dev/null || true
|
|
chown root:root "$dir" 2>/dev/null || true
|
|
}
|
|
|
|
ssh_monitor_secure_file() {
|
|
local file="$1"
|
|
local dir
|
|
[ -n "$file" ] || return 1
|
|
dir="$(dirname "$file")"
|
|
ssh_monitor_secure_dir "$dir" || true
|
|
if [ ! -f "$file" ]; then
|
|
: >"$file" 2>/dev/null || touch "$file" 2>/dev/null || return 1
|
|
fi
|
|
chmod 600 "$file" 2>/dev/null || true
|
|
chown root:root "$file" 2>/dev/null || true
|
|
}
|
|
|
|
# Существующий файл или каталог: 600/700 root:root; для отсутствующего пути — только родительский каталог.
|
|
ssh_monitor_harden_path() {
|
|
local path="$1"
|
|
[ -n "$path" ] || return 0
|
|
if [ -d "$path" ]; then
|
|
ssh_monitor_secure_dir "$path"
|
|
elif [ -f "$path" ] || [ -L "$path" ]; then
|
|
ssh_monitor_secure_file "$path"
|
|
else
|
|
local parent
|
|
parent="$(dirname "$path")"
|
|
[ -n "$parent" ] && [ "$parent" != "." ] && ssh_monitor_secure_dir "$parent"
|
|
fi
|
|
}
|
|
|
|
ssh_monitor_warn_path_perms() {
|
|
local path="$1" kind="$2" max_mode="${3:-600}"
|
|
local mode own msg
|
|
[ -e "$path" ] || return 0
|
|
if ! ssh_monitor_is_root_owned "$path"; then
|
|
own="$(ssh_monitor_path_owner "$path" 2>/dev/null || echo '?')"
|
|
msg="WARN: ${kind} ${path}: владелец ${own}, ожидается root:root"
|
|
printf '%s\n' "$msg" >&2
|
|
[ -n "${write_log:-}" ] && write_log "$msg" || true
|
|
fi
|
|
mode="$(ssh_monitor_path_mode "$path" 2>/dev/null || echo "")"
|
|
if [ -n "$mode" ] && [ "$((10#$mode))" -gt "$((10#$max_mode))" ]; then
|
|
msg="WARN: ${kind} ${path}: mode ${mode}, рекомендуется не шире ${max_mode}"
|
|
printf '%s\n' "$msg" >&2
|
|
[ -n "${write_log:-}" ] && write_log "$msg" || true
|
|
fi
|
|
}
|
|
|
|
ssh_monitor_check_config_file_perms() {
|
|
local file="${1:-/etc/ssh-monitor.conf}"
|
|
local strict="${2:-0}"
|
|
local mode msg
|
|
[ -f "$file" ] || return 0
|
|
if ! ssh_monitor_is_root_owned "$file"; then
|
|
msg="WARN: конфиг ${file}: владелец $(ssh_monitor_path_owner "$file" 2>/dev/null || echo '?'), ожидается root:root"
|
|
printf '%s\n' "$msg" >&2
|
|
[ -n "${write_log:-}" ] && write_log "$msg" || true
|
|
if ssh_monitor_truthy "$strict"; then
|
|
printf '%s\n' "CONFIG_STRICT_PERMS=1: исправьте владельца конфига (chown root:root ${file})" >&2
|
|
return 1
|
|
fi
|
|
fi
|
|
mode="$(ssh_monitor_path_mode "$file" 2>/dev/null || echo "")"
|
|
case "$mode" in
|
|
600 | 400) ;;
|
|
*)
|
|
msg="WARN: конфиг ${file}: mode ${mode:-?}, рекомендуется 600 или 400 (chmod 600 ${file})"
|
|
printf '%s\n' "$msg" >&2
|
|
[ -n "${write_log:-}" ] && write_log "$msg" || true
|
|
if ssh_monitor_truthy "$strict"; then
|
|
printf '%s\n' "CONFIG_STRICT_PERMS=1: ослабленные права конфига недопустимы" >&2
|
|
return 1
|
|
fi
|
|
;;
|
|
esac
|
|
return 0
|
|
}
|