191 lines
4.0 KiB
Bash
Executable File
191 lines
4.0 KiB
Bash
Executable File
#!/bin/bash
|
|
### Copyright 1999-2025. WebPros International GmbH. All rights reserved.
|
|
|
|
export LC_ALL="C" PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
|
|
unset GREP_OPTIONS
|
|
umask 022
|
|
|
|
prog="`basename $0`"
|
|
action="$1"
|
|
|
|
# Communication protocol with repaird is:
|
|
# * emit output to stdout as plaintext;
|
|
# * stderr is not shown to user, but may be logged by 'repaird -v 3';
|
|
# * last line of output is JSON with any remaining output (see result() below);
|
|
# * exit code is 0.
|
|
|
|
info()
|
|
{
|
|
echo "INFO: $*"
|
|
}
|
|
|
|
warn()
|
|
{
|
|
echo "WARNING: $*"
|
|
}
|
|
|
|
err()
|
|
{
|
|
echo "ERROR: $*"
|
|
}
|
|
|
|
die()
|
|
{
|
|
err "$@" | result "failed"
|
|
exit 0
|
|
}
|
|
|
|
success()
|
|
{
|
|
echo -n | result "ok"
|
|
exit 0
|
|
}
|
|
|
|
usage()
|
|
{
|
|
echo "Usage: $prog { --check | --repair }" >&2
|
|
exit 1
|
|
}
|
|
|
|
result()
|
|
{
|
|
local status="$1"
|
|
python3 -c 'import sys, json
|
|
message = sys.stdin.read()
|
|
status = sys.argv[1] if message.strip() else "ok"
|
|
print(json.dumps({"status": status, "message": message}))
|
|
' "$status"
|
|
}
|
|
|
|
is_remote_db_feature_enabled()
|
|
{
|
|
[ -s "/etc/psa/private/dsn.ini" ]
|
|
}
|
|
|
|
get_mysql_option_value()
|
|
{
|
|
local section="$1"
|
|
local name="$2"
|
|
local default="$3"
|
|
|
|
local value="`/usr/bin/my_print_defaults "$section" | sed -n "s/^--$name=//p" | tail -n 1`"
|
|
echo "${value:-$default}"
|
|
}
|
|
|
|
get_mysql_datadir()
|
|
{
|
|
get_mysql_option_value mysqld datadir "/var/lib/mysql"
|
|
}
|
|
|
|
find_psa_shadow()
|
|
{
|
|
find /etc/psa/.psa.shadow /etc/psa/private/secret_key "$@"
|
|
}
|
|
|
|
find_mysql_datadir()
|
|
{
|
|
find "$MYSQL_DATADIR" -maxdepth 0 "$@"
|
|
}
|
|
|
|
find_mysql_dirs()
|
|
{
|
|
find "$MYSQL_DATADIR" -mindepth 1 -type d ! \( -name 'lost+found' -o -name 'lost@002bfound' \) "$@"
|
|
}
|
|
|
|
find_mysql_files()
|
|
{
|
|
find "$MYSQL_DATADIR" -mindepth 1 -type f \
|
|
! \( -name 'debian-*.flag' -o -name 'mysql_upgrade_info' -o -name 'mariadb_upgrade_info' \) "$@"
|
|
}
|
|
|
|
declare -A PERMS=(
|
|
[find_psa_shadow]=" " # Use permissions fsmng knows about
|
|
|
|
# Ideally permission changes on MySQL files should be done with stopped MySQL, but we don't
|
|
# want the procedure to require downtime, so sacrifice some degree of correctness by skipping this.
|
|
[find_mysql_dirs]=" --perms 0700 --owner mysql --group mysql --filetype directory"
|
|
[find_mysql_files]=" --perms 0660,0600 --owner mysql --group mysql --filetype file"
|
|
[find_mysql_datadir]=" --perms 0755 --owner mysql --group mysql --filetype directory"
|
|
)
|
|
|
|
permissions()
|
|
{
|
|
local operation="$1"
|
|
[ "$operation" = "--check-ac" -o "$operation" = "--set-ac" ] || die "Unknown operation: $operation"
|
|
|
|
local restorecon_opts=(-iv)
|
|
[ "$operation" = "--set-ac" ] || restorecon_opts+=(-n)
|
|
|
|
local rc=0
|
|
|
|
for finder in "${!PERMS[@]}"; do
|
|
local perms="${PERMS[$finder]}"
|
|
$finder | "$PRODUCT_ROOT_D/admin/sbin/fsmng" "$operation" - $perms 2>&1 || rc="$?"
|
|
done
|
|
|
|
if command -v restorecon >/dev/null 2>&1 && should_check_selinux "$operation"; then
|
|
for finder in "${!PERMS[@]}"; do
|
|
$finder
|
|
done | restorecon -f - "${restorecon_opts[@]}" || rc="$?"
|
|
fi
|
|
|
|
return "$rc"
|
|
}
|
|
|
|
should_check_selinux()
|
|
{
|
|
local operation="$1"
|
|
local mode="`get_selinux_mode`"
|
|
|
|
if [ "$operation" = "--check-ac" -a "$mode" = "Enforcing" ]; then
|
|
# Check only in Enforcing mode
|
|
return 0
|
|
elif [ "$operation" = "--set-ac" -a "$mode" != "Disabled" ]; then
|
|
# Repair in Enforcing or Permissive mode
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
get_selinux_mode()
|
|
{
|
|
if ! command -v selinuxenabled >/dev/null 2>&1 || ! selinuxenabled; then
|
|
echo "Disabled"
|
|
elif ! command -v getenforce >/dev/null 2>&1; then
|
|
echo "Disabled"
|
|
else
|
|
getenforce || echo "Disabled"
|
|
fi
|
|
}
|
|
|
|
check()
|
|
{
|
|
! is_remote_db_feature_enabled || die "Cannot check permissions of MySQL-related files with a remote database."
|
|
permissions --check-ac | result "corrupted"
|
|
exit 0
|
|
}
|
|
|
|
repair()
|
|
{
|
|
! is_remote_db_feature_enabled || die "Cannot repair permissions of MySQL-related files with a remote database."
|
|
permissions --set-ac || die "Failed to repair some permissions of MySQL-related files."
|
|
success
|
|
}
|
|
|
|
PRODUCT_ROOT_D="/opt/psa"
|
|
MYSQL_DATADIR="`get_mysql_datadir`"
|
|
|
|
case "$action" in
|
|
--check)
|
|
check
|
|
;;
|
|
--repair)
|
|
repair
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
|
|
# vim:ft=sh
|