mirror of
https://github.com/SpotX-Official/SpotX-Bash.git
synced 2026-08-09 17:41:07 +10:00
Harden Linux client patching
This commit is contained in:
@@ -486,9 +486,22 @@ run_prepare() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check_write_permission() {
|
check_write_permission() {
|
||||||
local target_user="${SUDO_USER:-$(id -un)}"
|
local writePath
|
||||||
|
[[ "${platformType}" == "Linux" && -z "${SPOTX_BUILD_MODE}" ]] && ((EUID == 0)) && {
|
||||||
|
stagedInstall='true'
|
||||||
|
protectedInstall='true'
|
||||||
|
}
|
||||||
for path_to_check in "$@"; do
|
for path_to_check in "$@"; do
|
||||||
[[ ! -w "${path_to_check}" ]] && {
|
[[ -d "${path_to_check}" ]] && writePath="${path_to_check}" || writePath="${path_to_check%/*}"
|
||||||
|
[[ ! -w "${path_to_check}" ]] && stagedInstall='true'
|
||||||
|
[[ ! -w "${writePath}" ]] && {
|
||||||
|
stagedInstall='true'
|
||||||
|
protectedInstall='true'
|
||||||
|
((EUID == 0)) && continue
|
||||||
|
command -v sudo >/dev/null || {
|
||||||
|
echo -e "\n${red}Error:${clr} sudo command not found. Install sudo or run this script as root.\n" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
sudo -n true 2>/dev/null || {
|
sudo -n true 2>/dev/null || {
|
||||||
echo -e "${yellow}Warning:${clr} SpotX-Bash does not have write permission in client directory.\nRequesting sudo permission..." >&2
|
echo -e "${yellow}Warning:${clr} SpotX-Bash does not have write permission in client directory.\nRequesting sudo permission..." >&2
|
||||||
sudo -v || {
|
sudo -v || {
|
||||||
@@ -496,12 +509,152 @@ check_write_permission() {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sudo chown -R "${target_user}" "${path_to_check}"
|
|
||||||
sudo chmod -R u+rwX,go-w "${path_to_check}"
|
|
||||||
}
|
}
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sudo_run() {
|
||||||
|
if ((EUID == 0)) || [[ -z "${protectedInstall+x}" ]]; then
|
||||||
|
command "$@"
|
||||||
|
else
|
||||||
|
sudo "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
protected_stage_copy() {
|
||||||
|
local source="${1}" destination="${2}"
|
||||||
|
sudo_run cat -- "${source}" > "${destination}" || {
|
||||||
|
rm -f -- "${destination}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
chmod 600 "${destination}"
|
||||||
|
}
|
||||||
|
|
||||||
|
protected_stage_prepare() {
|
||||||
|
targetAppBinary="${appBinary}"
|
||||||
|
targetAppBak="${appBak}"
|
||||||
|
targetXpuiPath="${xpuiPath}"
|
||||||
|
targetXpuiSpa="${xpuiSpa}"
|
||||||
|
targetXpuiBak="${xpuiBak}"
|
||||||
|
linux_working_dir
|
||||||
|
appPath="${workDir}/client"
|
||||||
|
appBinary="${appPath}/spotify"
|
||||||
|
appBak="${appBinary}.bak"
|
||||||
|
xpuiPath="${appPath}/Apps"
|
||||||
|
xpuiBak="${xpuiPath}/xpui.bak"
|
||||||
|
xpuiDir="${xpuiPath}/xpui"
|
||||||
|
xpuiSpa="${xpuiPath}/xpui.spa"
|
||||||
|
dwpPanelSectionJs="${xpuiDir}/dwp-panel-section.js"
|
||||||
|
homeHptoJs="${xpuiDir}/home-hpto.js"
|
||||||
|
homeV2Js="${xpuiDir}/home-v2.js"
|
||||||
|
indexHtml="${xpuiDir}/index.html"
|
||||||
|
vendorXpuiJs="${xpuiDir}/vendor~xpui.js"
|
||||||
|
xpuiCss="${xpuiDir}/xpui.css"
|
||||||
|
xpuiDesktopModalsJs="${xpuiDir}/xpui-desktop-modals.js"
|
||||||
|
xpuiJs="${xpuiDir}/xpui.js"
|
||||||
|
xpuiSnapshotJs="${xpuiDir}/xpui-snapshot.js"
|
||||||
|
mkdir -p "${xpuiPath}" || exit 1
|
||||||
|
protected_stage_copy "${targetAppBinary}" "${appBinary}" || exit 1
|
||||||
|
protected_stage_copy "${targetXpuiSpa}" "${xpuiSpa}" || exit 1
|
||||||
|
[[ -f "${targetAppBak}" ]] && protected_stage_copy "${targetAppBak}" "${appBak}"
|
||||||
|
[[ -f "${targetXpuiBak}" ]] && protected_stage_copy "${targetXpuiBak}" "${xpuiBak}"
|
||||||
|
}
|
||||||
|
|
||||||
|
protected_prepare_file() {
|
||||||
|
local source="${1}" destination="${2}" reference="${3}" tempFile
|
||||||
|
tempFile=$(sudo_run mktemp "${destination}.spotx.XXXXXXXX") || return 1
|
||||||
|
sudo_run cp -a -- "${reference}" "${tempFile}" &&
|
||||||
|
sudo_run cp -- "${source}" "${tempFile}" &&
|
||||||
|
sudo_run chown --reference="${reference}" "${tempFile}" &&
|
||||||
|
sudo_run chmod --reference="${reference}" "${tempFile}" &&
|
||||||
|
sudo_run touch -r "${reference}" "${tempFile}" || {
|
||||||
|
sudo_run rm -f -- "${tempFile}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
printf '%s\n' "${tempFile}"
|
||||||
|
}
|
||||||
|
|
||||||
|
protected_save_destination() {
|
||||||
|
local destination="${1}" tempFile
|
||||||
|
[[ -e "${destination}" ]] || return 0
|
||||||
|
tempFile=$(sudo_run mktemp "${destination}.spotx-rollback.XXXXXXXX") || return 1
|
||||||
|
sudo_run cp -a -- "${destination}" "${tempFile}" || {
|
||||||
|
sudo_run rm -f -- "${tempFile}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
printf '%s\n' "${tempFile}"
|
||||||
|
}
|
||||||
|
|
||||||
|
protected_restore_destination() {
|
||||||
|
local backup="${1}" destination="${2}" existed="${3}"
|
||||||
|
[[ "${existed}" ]] && sudo_run mv -f -- "${backup}" "${destination}" || sudo_run rm -f -- "${destination}"
|
||||||
|
}
|
||||||
|
|
||||||
|
protected_remove_files() {
|
||||||
|
local file
|
||||||
|
for file in "$@"; do
|
||||||
|
[[ -n "${file}" ]] && sudo_run rm -f -- "${file}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
protected_commit() {
|
||||||
|
local uninstall="${1:-}" appFile spaFile appBakFile='' xpuiBakFile=''
|
||||||
|
local appRollback='' spaRollback='' appBakRollback='' xpuiBakRollback=''
|
||||||
|
local appExisted='' spaExisted='' appBakExisted='' xpuiBakExisted=''
|
||||||
|
local appBakReference="${targetAppBinary}" xpuiBakReference="${targetXpuiSpa}"
|
||||||
|
[[ -f "${appBinary}" && -f "${xpuiSpa}" ]] || return 1
|
||||||
|
unzip -tqq "${xpuiSpa}" || return 1
|
||||||
|
appFile=$(protected_prepare_file "${appBinary}" "${targetAppBinary}" "${targetAppBinary}") || return 1
|
||||||
|
spaFile=$(protected_prepare_file "${xpuiSpa}" "${targetXpuiSpa}" "${targetXpuiSpa}") || {
|
||||||
|
sudo_run rm -f -- "${appFile}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
[[ -z "${uninstall}" ]] && {
|
||||||
|
[[ -e "${targetAppBak}" ]] && appBakReference="${targetAppBak}"
|
||||||
|
[[ -e "${targetXpuiBak}" ]] && xpuiBakReference="${targetXpuiBak}"
|
||||||
|
appBakFile=$(protected_prepare_file "${appBak}" "${targetAppBak}" "${appBakReference}") || {
|
||||||
|
sudo_run rm -f -- "${appFile}" "${spaFile}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
xpuiBakFile=$(protected_prepare_file "${xpuiBak}" "${targetXpuiBak}" "${xpuiBakReference}") || {
|
||||||
|
sudo_run rm -f -- "${appFile}" "${spaFile}" "${appBakFile}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[[ -e "${targetAppBinary}" ]] && appExisted='true'
|
||||||
|
[[ -e "${targetXpuiSpa}" ]] && spaExisted='true'
|
||||||
|
[[ -e "${targetAppBak}" ]] && appBakExisted='true'
|
||||||
|
[[ -e "${targetXpuiBak}" ]] && xpuiBakExisted='true'
|
||||||
|
{
|
||||||
|
appRollback=$(protected_save_destination "${targetAppBinary}") &&
|
||||||
|
spaRollback=$(protected_save_destination "${targetXpuiSpa}")
|
||||||
|
[[ "${uninstall}" ]] || {
|
||||||
|
appBakRollback=$(protected_save_destination "${targetAppBak}") &&
|
||||||
|
xpuiBakRollback=$(protected_save_destination "${targetXpuiBak}")
|
||||||
|
}
|
||||||
|
} || {
|
||||||
|
protected_remove_files "${appFile}" "${spaFile}" "${appBakFile}" "${xpuiBakFile}"
|
||||||
|
protected_remove_files "${appRollback}" "${spaRollback}" "${appBakRollback}" "${xpuiBakRollback}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
{
|
||||||
|
{ [[ "${uninstall}" ]] || sudo_run mv -f -- "${appBakFile}" "${targetAppBak}"; } &&
|
||||||
|
{ [[ "${uninstall}" ]] || sudo_run mv -f -- "${xpuiBakFile}" "${targetXpuiBak}"; } &&
|
||||||
|
sudo_run mv -f -- "${appFile}" "${targetAppBinary}" &&
|
||||||
|
sudo_run mv -f -- "${spaFile}" "${targetXpuiSpa}"
|
||||||
|
} || {
|
||||||
|
protected_restore_destination "${appRollback}" "${targetAppBinary}" "${appExisted}"
|
||||||
|
protected_restore_destination "${spaRollback}" "${targetXpuiSpa}" "${spaExisted}"
|
||||||
|
[[ "${uninstall}" ]] || protected_restore_destination "${appBakRollback}" "${targetAppBak}" "${appBakExisted}"
|
||||||
|
[[ "${uninstall}" ]] || protected_restore_destination "${xpuiBakRollback}" "${targetXpuiBak}" "${xpuiBakExisted}"
|
||||||
|
protected_remove_files "${appFile}" "${spaFile}" "${appBakFile}" "${xpuiBakFile}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
protected_remove_files "${appRollback}" "${spaRollback}" "${appBakRollback}" "${xpuiBakRollback}"
|
||||||
|
[[ "${uninstall}" ]] && sudo_run rm -f -- "${targetAppBak}" "${targetXpuiBak}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
uninstall_spotx() {
|
uninstall_spotx() {
|
||||||
rm -f "${appBinary}" 2>/dev/null
|
rm -f "${appBinary}" 2>/dev/null
|
||||||
mv -f "${appBak}" "${appBinary}"
|
mv -f "${appBak}" "${appBinary}"
|
||||||
@@ -517,12 +670,20 @@ run_uninstall_check() {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
check_write_permission "${appPath}" "${appBinary}" "${xpuiPath}" "${xpuiSpa}"
|
check_write_permission "${appPath}" "${appBinary}" "${xpuiPath}" "${xpuiSpa}"
|
||||||
|
[[ "${platformType}" == "Linux" && "${stagedInstall}" ]] && protected_stage_prepare
|
||||||
[[ "${cleanAB}" ]] && {
|
[[ "${cleanAB}" ]] && {
|
||||||
echo -e "${yellow}Warning:${clr} SpotX-Bash has detected abnormal behavior.\nClient reinstallation may be required...\n" >&2
|
echo -e "${yellow}Warning:${clr} SpotX-Bash has detected abnormal behavior.\nClient reinstallation may be required...\n" >&2
|
||||||
rm -f "${appBak}" 2>/dev/null
|
rm -f "${appBak}" 2>/dev/null
|
||||||
rm -f "${xpuiBak}" 2>/dev/null
|
rm -f "${xpuiBak}" 2>/dev/null
|
||||||
|
[[ "${platformType}" == "Linux" && "${stagedInstall}" ]] && sudo_run rm -f -- "${targetAppBak}" "${targetXpuiBak}"
|
||||||
} || {
|
} || {
|
||||||
uninstall_spotx
|
uninstall_spotx
|
||||||
|
[[ "${platformType}" == "Linux" && "${stagedInstall}" ]] && {
|
||||||
|
protected_commit 'true' || {
|
||||||
|
echo -e "\n${red}Error:${clr} Failed to restore client. Original files restored.\n" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printf "\xE2\x9C\x94\x20\x46\x69\x6E\x69\x73\x68\x65\x64\x20\x75\x6E\x69\x6E\x73\x74\x61\x6C\x6C\n\n"
|
printf "\xE2\x9C\x94\x20\x46\x69\x6E\x69\x73\x68\x65\x64\x20\x75\x6E\x69\x6E\x73\x74\x61\x6C\x6C\n\n"
|
||||||
exit 0
|
exit 0
|
||||||
@@ -584,7 +745,25 @@ sudo_check() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
linux_working_dir() { [[ -d "/tmp" ]] && workDir="/tmp" || workDir="$HOME"; }
|
cleanup_work_dir() {
|
||||||
|
[[ -n "${workDir:-}" && -d "${workDir}" && "${workDir##*/}" == spotx-bash.* ]] && rm -rf -- "${workDir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
linux_working_dir() {
|
||||||
|
local tempBase="${TMPDIR:-/tmp}"
|
||||||
|
[[ -n "${workDir:-}" && -d "${workDir}" && "${workDir##*/}" == spotx-bash.* ]] && return
|
||||||
|
[[ "${tempBase}" == /* && -d "${tempBase}" && -w "${tempBase}" ]] || tempBase="/tmp"
|
||||||
|
workDir=$(mktemp -d "${tempBase%/}/spotx-bash.XXXXXXXX") || {
|
||||||
|
echo -e "${red}Error:${clr} Failed to create temporary working directory.\n" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
trap cleanup_work_dir EXIT
|
||||||
|
trap 'exit 130' HUP INT TERM
|
||||||
|
chmod 700 "${workDir}" || {
|
||||||
|
echo -e "${red}Error:${clr} Failed to secure temporary working directory.\n" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
linux_deb_install() {
|
linux_deb_install() {
|
||||||
sudo_check
|
sudo_check
|
||||||
@@ -826,6 +1005,7 @@ xpui_open() {
|
|||||||
run_core_start() {
|
run_core_start() {
|
||||||
final_setup_check
|
final_setup_check
|
||||||
check_write_permission "${appPath}" "${appBinary}" "${xpuiPath}" "${xpuiSpa}"
|
check_write_permission "${appPath}" "${appBinary}" "${xpuiPath}" "${xpuiSpa}"
|
||||||
|
[[ "${platformType}" == "Linux" && "${stagedInstall}" ]] && protected_stage_prepare
|
||||||
xpui_detect
|
xpui_detect
|
||||||
[[ "${xpuiSkip}" ]] && { printf "\xE2\x9C\x94\x20\x46\x69\x6E\x69\x73\x68\x65\x64\n\n"; exit 0; }
|
[[ "${xpuiSkip}" ]] && { printf "\xE2\x9C\x94\x20\x46\x69\x6E\x69\x73\x68\x65\x64\n\n"; exit 0; }
|
||||||
xpui_open
|
xpui_open
|
||||||
@@ -890,6 +1070,12 @@ run_finish() {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
rm -rf "${xpuiDir}"
|
rm -rf "${xpuiDir}"
|
||||||
|
[[ "${platformType}" == "Linux" && "${stagedInstall}" ]] && protected_commit || {
|
||||||
|
[[ "${platformType}" == "Linux" && "${stagedInstall}" ]] && {
|
||||||
|
echo -e "\n${red}Error:${clr} Failed to install patched client. Original files restored.\n" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
[[ "${platformType}" == "macOS" ]] && {
|
[[ "${platformType}" == "macOS" ]] && {
|
||||||
[[ "${skipCodesign}" ]] && /usr/bin/xattr -cr "${appPath}" 2>/dev/null || {
|
[[ "${skipCodesign}" ]] && /usr/bin/xattr -cr "${appPath}" 2>/dev/null || {
|
||||||
/usr/bin/xattr -cr "${appPath}" 2>/dev/null
|
/usr/bin/xattr -cr "${appPath}" 2>/dev/null
|
||||||
|
|||||||
Reference in New Issue
Block a user