#!/bin/bash

###################################################################################################
# Script Name:  Patch-SPSSLog4jShellVulnerability.sh
# By:  Zack Thompson / Created:  4/5/2022
# Version:  1.0.0 / Updated:  4/5/2022 / By:  ZT
#
# Description:  Remove and replace vulnerable log4j files with patched versions in SPSS.
#
###################################################################################################

echo -e "\n*****  Patch SPSS Log4j Process:  START  *****\n"

##################################################
# Define Variables

# Set the current patched version
patched_version="2.17.1"

# Set working directory
pkg_dir=$( /usr/bin/dirname "${0}" )

# Default notification icon
icon="/System/Library/CoreServices/Problem Reporter.app/Contents/Resources/ProblemReporter.icns"

##################################################
# Functions

app_running() {

	# Arguments
	# $1 = (regex str) A Regex string to pass to `grep -E` to parse for a running application

	local app="${1}"

	# Check if app is running
	/bin/ps -ax -o pid,command | /usr/bin/grep -E "${app}" | /usr/bin/grep -v "grep"

}

patch_spss() {

	# Arguments
	# $1 = (array) List of vulnerable jar files
	local vulnerable_jars="${1}"

	declare -a file_paths_to_install_patches=()

	# If multiple vulnerable jars were found, loop through them.
	while IFS=$'\n' read -r vulnerable_jar; do

		# Get the file name
		file_name=$( echo "${vulnerable_jar}" | /usr/bin/awk -F "/" '{print $NF}' )

		# Get the path of the file
		file_path=$( echo "${vulnerable_jar}" | /usr/bin/awk -F "/${file_name}" '{print $1}' )

		file_paths_to_install_patches+=("${file_path}")

		echo "Removing vulnerable jar:  ${vulnerable_jar}"
		/bin/rm -Rf "${vulnerable_jar}"

	done < <( echo "${vulnerable_jars}" )

	for patch_path in "${file_paths_to_install_patches[@]}"; do

		echo "Installing patched jars into:  ${patch_path}"
		/bin/cp "${pkg_dir}/patched_files/"* "${patch_path}/"

	done

	echo "All vulnerable jars have been replaced!"

}

jamf_helper() {

	# Arguments
	# $1 = (str) Window Type
	# $2 = (str) Path to an icon
	# $3 = (str) Title
	# $4 = (str) Heading
	# $5 = (str) Description
	# $6 = (str) Extra parameters

	local binary="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
	local window_type="${1}"
	local icon="${2}"
	local title="${3}"
	local heading="${4}"
	local description="${5}"
	local extra_parameters="${6}"

	# Prompt user via Jamf Helper
	# shellcheck disable=SC2086
	"${binary}" -windowType "${window_type}" -title "${title}" -icon "${icon}" -heading "${heading}" -description "${description}" $extra_parameters > /dev/null 2>&1

}

##################################################
# Bits staged...

if [[ ! -e "${pkg_dir}" ]]; then

	echo "Patch directory could not be found!"
	exit 1

fi

echo "Searching for vulnerable log4j jars..."
vulnerable_jars=$( /usr/bin/find -E /Applications -iregex ".*[/](SPSS) ?(Statistics) ?([0-9]{2})?[.]app/Contents/.+/.*log4j.+\.jar" -not -iregex ".*[/](SPSS) ?(Statistics) ?([0-9]{2})?[.]app/Contents/.+/.*log4j.+(${patched_version})\.jar" -type f -prune )

if [[ -z "${vulnerable_jars}" ]]; then

	echo "No vulnerable jars found"

else

	# Check if SPSS is running
	running=$( app_running "/Applications/.*[/](SPSS) ?(Statistics) ?([0-9]{2})?[.]app" )

	while [[ -n "${running}" ]]; do

		echo "SPSS is currently running, prompt user."
		user_was_prompted="true"

		if [[ -z $spss_app_bundles ]]; then

			spss_app_bundles=$( /usr/bin/find -E /Applications -iregex ".*[/](SPSS) ?(Statistics) ?([0-9]{2})?[.]app" -type d -prune )
			spss_icon_file_name=$( /usr/bin/defaults read "${spss_app_bundles##*$'\n'}/Contents/Info.plist" "CFBundleIconFile" )

			if [[ -e "${spss_app_bundles##*$'\n'}/Contents/Resources/${spss_icon_file_name}" ]]; then

				icon="${spss_app_bundles##*$'\n'}/Contents/Resources/${spss_icon_file_name}"

			fi

		fi

		window_type="utility"
		title="Security Patch Notification"
		heading="<Insert Organization>"
		description="SPSS Statistics needs to be updated to patch a security vulnerability.  Please quit SPSS Statistics and click 'OK' to apply this update.

Clicking 'Cancel' will allow you to delay the security patch and you will be prompted again to apply the patch.

If you have questions, please contact your deskside support group."

		# Prompt user via Jamf Helper
		jamf_helper "${window_type}" "${icon}" "${title}" "${heading}" "${description}" "-button1 \"OK\" -button2 \"Cancel\""
		user_selection=$?

		if [[ $user_selection == 0 ]]; then
			echo "User clicked OK"

			/bin/sleep 5
			# Check if SPSS is running
			running=$( app_running "/Applications/.*[/](SPSS) ?(Statistics) ?([0-9]{2})?[.]app" )

		elif [[ $user_selection == 2 ]]; then

			echo "User canceled the process.  Aborting..."
			echo "*****  Patch SPSS Log4j Process:  CANCELED  *****"
			exit 4

		fi

	done

	echo "Patching..."
	patch_spss "${vulnerable_jars}"

	if [[ "${user_was_prompted}" == "true" ]]; then

		descriptionComplete="SPSS Statistics has been patched!

Thank you for taking the time to ensure our systems are secure!"

		# Prompt user via Jamf Helper
		jamf_helper "${window_type}" "${icon}" "${title}" "${heading}" "${descriptionComplete}" "-button1 \"Close\" -defaultButton 1"
		user_selection=$?

	fi

fi

echo -e "\n*****  Patch SPSS Log4j Process:  COMPLETE  *****"
exit 0