#!/bin/bash
# When using "INTERACTIVEMODE=no" there are dependencies on macOS 11.3 and above as well as the System Extension removal.
# The System Extension must be removed by your MDM prior to running the below script as both require a reboot.

# Set interactivemode to 'no' for automated uninstall and reboot see above dependencies.
INTERACTIVEMODE=yes

brands=(
    "Thycotic"
    "Delinea"
)

rights=(
    "com.apple.desktopservices"
    "system.preferences"
    "system.preferences.datetime"
    "system.preferences.energysaver"
    "system.preferences.network"
    "system.install.software"
)

customRights=(
    "ACSAppCopy"
    "ACSEvaluatePreferencePane"
    "preferences.acsagent"
    "ACSAdHoc"
    "ACSInstallSoftware"
)

function restoreAuthorizationdbRight {
	right=$1
	rfile="/Library/Application Support/$2/Agent/$right"
	if [[ "$1" == *.backup ]]; then
		# Chop .backup
		right=${right%.backup}
		# Just the filename as the right now
		right=${right##*/}
		rfile="/Library/Application Support/$2/Agent/$right.backup"
	fi
	echo -n "Checking for existing $rfile..."
	if [[ -f $rfile ]]; then
		echo "detected -- restoring $right right"
		security authorizationdb write $right < "$rfile"
	else
		echo "not detected."
	fi
}

function removeCustomRight {
	right="com.$2.$1"
	echo -n "Removing custom right '$right'..."
	security authorizationdb remove $right
}

if [[ $INTERACTIVEMODE == yes ]]; then
	if [ "$EUID" -ne 0 ]; then
		echo "Error. You need to run this script as root. Re-run this script using sudo, e.g. \"sudo $0\""
		exit 5
	fi

	while true; do
		read -p "This will uninstall the Privilege Manager Agent from this computer. Continue [Y/N]? " yn
		case $yn in
			[Yy]* ) break;;
			[Nn]* ) exit;;
			* ) echo "Please answer Y or N.";;
		esac
	done
fi

INSTALLER_USER=$(/usr/bin/stat -f '%Su' $HOME)
INSTALLER_UID=$(/usr/bin/id -u $INSTALLER_USER)

echo "Uninstalling Privilege Manager Agent."

echo "Making Installer the default installer"
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -u /Applications/Privilege\ Manager.app

# Do the following for each brand.
for brand in "${brands[@]}"; do
	brand_lc=$(echo $brand | tr '[:upper:]' '[:lower:]')
	echo "Uninstalling $brand ($brand_lc) Privilege Manager Agent."

	for d in /Users/*/; do
		pfile=$d"Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist";
		if [ -f "$pfile" ]; then
			user=$(echo $pfile | sed 's/\/Users\///g')
			user=$(echo $user | sed 's/\/Library\/Preferences\/com.apple.LaunchServices\/com.apple.launchservices.secure.plist//g')
			prefs=$(defaults read "$pfile" LSHandlers)
			prefs2=$(echo $prefs | sed "s/com.$brand_lc.privilegemanagergui/com.apple.installer/g")
			defaults write "$pfile" LSHandlers "$prefs2"
			chown $user "$pfile"
			touch "$pfile"
			echo "Updated $pfile"
		fi
	done

	echo -n "Checking for ACS GUI..."
	if [[ -f "/Library/LaunchAgents/com.$brand_lc.acsgui.plist" ]]; then
		# launchctl bootout will return 36 (EINPROGRESS). Check for that and remove if necessary.
		/bin/launchctl bootout gui/$INSTALLER_UID "/Library/LaunchAgents/com.$brand_lc.acsgui.plist"
		if [[ $? -eq 36 || $? -eq 0 ]]; then
			echo "detected -- removing."
			rm -f "/Library/LaunchAgents/com.$brand_lc.acsgui.plist"
		else
			echo "not detected."
		fi
	else
		echo "not detected."
	fi

	echo -n "Checking for ACS daemon..."
	if /bin/launchctl list "UJDHBB2D6Q.com.$brand_lc.acsd" &> /dev/null; then
		echo "detected -- removing."
		/Applications/Privilege\ Manager.app/Contents/MacOS/Privilege\ Manager --unload-system-extension
		/bin/launchctl remove com.$brand_lc.acsd
		sleep 1
	else
		echo "not detected."
	fi

	EVENTUPLOADERD_FOUND=0
	echo -n "Checking for event uploader daemon..."
	if /bin/launchctl list "com.$brand_lc.pmeventuploaderd" &> /dev/null; then
		EVENTUPLOADERD_FOUND=1
		/bin/launchctl bootout system/"com.$brand_lc.pmeventuploaderd"
		rm -f "/Library/LaunchDaemons/com.$brand_lc.pmeventuploaderd.plist"
	fi
	if /bin/launchctl list "com.$brand_lc.pmeventuploaderd.retryerrors" &> /dev/null; then
		EVENTUPLOADERD_FOUND=1
		/bin/launchctl bootout system/"com.$brand_lc.pmeventuploaderd.retryerrors"
		rm -f "/Library/LaunchDaemons/com.$brand_lc.pmeventuploaderd.retryerrors.plist"
	fi
	if [[ $EVENTUPLOADERD_FOUND -ne 0 ]]; then
		echo "detected -- removing."
	else
		echo "not detected."
	fi

	for right in "${rights[@]}"; do
		restoreAuthorizationdbRight "$right" "$brand"
	done

	for right in "${customRights[@]}"; do
		removeCustomRight "$right" "$brand_lc"
	done

	echo "Checking for authorizationdb right backup files..."
	if [[ -d "/Library/Application Support/$brand/Agent" ]]; then
		echo "Restoring authorizationdb right backup files in /Library/Application Support/$brand/Agent..."
		bdir="/Library/Application Support/$brand/Agent/"
		for backup in "$bdir"*.backup; do
			echo "Restoring backup file - $backup"
			restoreAuthorizationdbRight "$backup" "$brand"
		done
	fi

	echo -n "Checking for application support agent files..."
	if [[ -d "/Library/Application Support/$brand/Agent" ]]; then
		echo "detected -- removing."
		rm -Rf "/Library/Application Support/$brand/Agent/"
		spath="/Library/Application Support/$brand"
		if [ $(ls -A "$spath" | wc -l) -eq 0 ]; then
			echo "Removing empty Delinea directory in /Library/Application Support"
			rm -Rf "$spath"
		fi
	else
		echo "not detected."
	fi
    
    echo -n "Checking for application support framework files..."
    if [[ -d "/Library/Application Support/$brand/Frameworks" ]]; then
        echo "detected -- removing."
        rm -Rf "/Library/Application Support/$brand/Frameworks/"
        spath="/Library/Application Support/$brand"
        if [ $(ls -A "$spath" | wc -l) -eq 0 ]; then
            echo "Removing empty Delinea directory in /Library/Application Support"
            rm -Rf "$spath"
        fi
    else
        echo "not detected."
    fi

	echo -n "Checking for application binaries..."
	if [[ -d "/usr/local/$brand_lc/agent" ]]; then
		echo "detected -- removing."
		rm -Rf "/usr/local/$brand_lc/agent"

		if ! find "/usr/local/$brand_lc" -mindepth 1 -print -quit 2> /dev/null | grep -q .; then
			echo "Removing empty directory: /usr/local/$brand_lc"
			rm -Rf "/usr/local/$brand_lc"
		fi
	else
		echo "not detected."
	fi

	echo -n "Checking for sudo plugin..."
	if [[ -f "/usr/local/libexec/sudo/${brand_lc}_plugin.so" ]]; then
		echo "detected -- removing."
		rm -f "/usr/local/libexec/sudo/${brand_lc}_plugin.so"
	else
		echo "not detected."
	fi

	echo -n "Checking for system logging preference file /Library/Preferences/Logging/Subsystems/com.$brand_lc.acs.plist..."
	if [[ -f "/Library/Preferences/Logging/Subsystems/com.$brand_lc.acs.plist" ]]; then
		echo "detected -- removing"
		rm -f "/Library/Preferences/Logging/Subsystems/com.$brand_lc.acs.plist"
	else
		echo "not detected."
	fi

	echo -n "Checking for installation log files..."
	if [[ -d "/var/log/$brand_lc" ]]; then
		echo "detected -- removing."
		rm -Rf "/var/log/$brand_lc"
	else
		echo "not detected."
	fi

	installlog="/var/log/$brand_lc-install.log"
	echo -n "Checking for install log file '$installlog'..."
	if [[ -f $installlog ]]; then
		echo "detected -- removing"
		rm -f "$installlog"
	else
		echo "not detected."
	fi
done

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -r -domain local -domain system -domain user

echo -n "Checking for legacy core agent..."
if /bin/launchctl list "com.thycotic.agent" &> /dev/null; then
	echo "detected -- removing."
	/bin/launchctl unload -w "/Library/LaunchDaemons/com.thycotic.agent.plist"
	rm -f "/Library/LaunchDaemons/com.thycotic.agent.plist"
else
	echo "not detected."
fi

EVENTPROCESSOR_FOUND=0
echo -n "Checking for existing event processor daemon..."
if /bin/launchctl list "com.delinea.pmeventprocessord" &> /dev/null; then
    EVENTPROCESSOR_FOUND=1
    /bin/launchctl bootout system/com.delinea.pmeventprocessord
    rm -f "/Library/LaunchDaemons/com.delinea.pmeventprocessord.plist"
fi
if [[ $EVENTPROCESSOR_FOUND -ne 0 ]]; then
    echo "detected -- removing."
else
    echo "not detected."
fi

FILEINVENTORY_FOUND=0
echo -n "Checking for existing file inventory daemon..."
if /bin/launchctl list "com.delinea.pmfileinventoryd" &> /dev/null; then
    FILEINVENTORY_FOUND=1
    /bin/launchctl bootout system/com.delinea.pmfileinventoryd
    rm -f "/Library/LaunchDaemons/com.delinea.pmfileinventoryd.plist"
fi
if [[ $FILEINVENTORY_FOUND -ne 0 ]]; then
    echo "detected -- removing."
else
    echo "not detected."
fi

LOCALSECURITY_FOUND=0
echo -n "Checking for existing local security daemon..."
if /bin/launchctl list "com.delinea.pmlocalsecurityd" &> /dev/null; then
    LOCALSECURITY_FOUND=1
    /bin/launchctl bootout system/com.delinea.pmlocalsecurityd
    rm -f "/Library/LaunchDaemons/com.delinea.pmlocalsecurityd.plist"
fi
if [[ $LOCALSECURITY_FOUND -ne 0 ]]; then
    echo "detected -- removing."
else
    echo "not detected."
fi

echo -n "Checking for legacy kernel extension..."
if [[ -d "/Library/Extensions/ThycoticACS.kext" ]]; then
	echo "detected -- removing."
	/sbin/kextunload "/Library/Extensions/ThycoticACS.kext"
	rm -Rf "/Library/Extensions/ThycoticACS.kext/"
else
	echo "not detected."
fi

echo -n "Checking for legacy certificate store..."
if [[ -d "/var/root/.dotnet/corefx/cryptography/x509stores/thycotic agent" ]]; then
        echo "detected -- removing."
        rm -Rf "/var/root/.dotnet/corefx/cryptography/x509stores/thycotic agent"
else
        echo "not detected."
fi

ApplicationScripts="Application Scripts/com.thycotic.privilegemanagergui.ACSFinderSyncExtension"
GroupContainers="Group Containers/com.thycotic.privman"
Containers="Containers/com.thycotic.privilegemanagergui.ACSFinderSyncExtension"
echo -n "Checking for existing support files in '/Users/~/Library'..."
for u in /Users/*; do
    echo -n "Checking for Caches in '$u/Library/Caches'..."
    if [[ -d "$u/Library/Caches/com.thycotic.acsd" ]]; then
        echo "detected -- removing."
        rm -Rf "$u/Library/Caches/com.thycotic.acsd"
    else
        echo "not detected."
    fi

	for brand in "${brands[@]}"; do
		brand_lc=$(echo $brand | tr '[:upper:]' '[:lower:]')

		echo -n "Checking for HTTPStorages in '$u/Library/HTTPStorages'..."
		if [[ -d "$u/Library/HTTPStorages/com.$brand_lc.privilegemanagergui" ]]; then
			echo "detected -- removing."
			rm -Rf "$u/Library/HTTPStorages/com.$brand_lc.privilegemanagergui"
		else
			echo "not detected."
		fi

		echo -n "Checking for support files in '$u/Library/Application Support/$brand'..."
		if [[ -d "$u/Library/Application Support/$brand" ]]; then
			echo "detected -- removing."
			rm -Rf "$u/Library/Application Support/$brand"

			if ! find "$u/Library/Application Support/$brand" -mindepth 1 -print -quit 2> /dev/null | grep -q .; then
				echo "Removing empty directory: $u/Library/Application Support/$brand"
				rm -Rf "$u/Library/Application Support/$brand"
			fi
		else
			echo "not detected."
		fi
	done

	echo -n "Checking for existing support files in '$u/Library/$ApplicationScripts'..."
	if [[ -d "$u/Library/$ApplicationScripts" ]]; then
		echo "detected -- removing."
		rm -Rf "$u/Library/$ApplicationScripts"

		if ! find "$u/Library/$ApplicationScripts" -mindepth 1 -print -quit 2> /dev/null | grep -q .; then
			echo "Removing empty directory: $u/Library/$ApplicationScripts"
			rm -Rf "$u/Library/$ApplicationScripts"
		fi
	else
		echo "not detected."
	fi

	echo -n "Checking for existing support files in '$u/Library/$GroupContainers'..."
	if [[ -d "$u/Library/$GroupContainers" ]]; then
		echo "detected -- removing."
		rm -Rf "$u/Library/$GroupContainers"

		if ! find "$u/Library/$GroupContainers" -mindepth 1 -print -quit 2> /dev/null | grep -q .; then
			echo "Removing empty directory: $u/Library/$GroupContainers"
			rm -Rf "$u/Library/$GroupContainers"
		fi
	else
		echo "not detected."
	fi

	echo -n "Checking for existing support files in '$u/Library/$Containers'..."
	if [[ -d "$u/Library/$Containers" ]]; then
		echo "detected -- removing."
		rm -Rf "$u/Library/$Containers"

		if ! find "$u/Library/$Containers" -mindepth 1 -print -quit 2> /dev/null | grep -q .; then
			echo "Removing empty directory: $u/Library/$Containers"
			rm -Rf "$u/Library/$Containers"
		fi
	else
		echo "not detected."
	fi
done

echo -n "Checking for existing Privilege Manager application..."
if [[ -d "/Applications/Privilege Manager.app" ]]; then
	echo "detected -- removing."
	rm -Rf "/Applications/Privilege Manager.app"
else
	echo "not detected."
fi

echo -n "Checking for existing Privilege Manager Authorization Plugin..."
if [[ -d "/Library/Security/SecurityAgentPlugins/ACSAuthPlugin.bundle" ]]; then
	echo "detected -- removing."
	rm -Rf "/Library/Security/SecurityAgentPlugins/ACSAuthPlugin.bundle"
else
	echo "not detected."
fi

echo -n "Checking for legacy Privilege Manager Authorization Plugin..."
if [[ -d "/Library/Security/SecurityAgentPlugins/ACSAppCopy.bundle" ]]; then
	echo "detected -- removing."
	rm -Rf "/Library/Security/SecurityAgentPlugins/ACSAppCopy.bundle"
else
	echo "not detected."
fi

echo -n "Checking for Privilege Manager Agent Preference Pane..."
if [[ -d "/Library/PreferencePanes/ACSAgent.prefPane" ]]; then
	echo "detected -- removing."
	rm -Rf "/Library/PreferencePanes/ACSAgent.prefPane"
else
	echo "not detected."
fi

echo -n "Checking for pmagentctl..."
if [[ -f "/usr/local/bin/pmagentctl" ]]; then
	echo "detected -- removing."
	rm -f "/usr/local/bin/pmagentctl"
else
	echo "not detected."
fi

echo -n "Checking for sudo configuration..."
if [[ -f "/etc/sudo.conf" ]]; then
	echo "detected -- moving aside."
	mv "/etc/sudo.conf" "/etc/sudo-delinea.conf"
else
	echo "not detected."
fi

echo -n "Checking for native core agent..."
if /bin/launchctl list "com.delinea.pmcored" &> /dev/null; then
    echo "detected -- removing."
    /bin/launchctl bootout system/com.delinea.pmcored
    rm -f "/Library/LaunchDaemons/com.delinea.pmcored.plist"
else
    echo "not detected."
fi

echo "Removing _privman service account if it exists..."
sysadminctl -deleteUser _privman

echo -n "Removing package receipt..."
/usr/sbin/pkgutil --forget com.thycotic.agent
/usr/sbin/pkgutil --forget com.delinea.pm.agent

echo "Uninstall complete."
echo "--"
echo "The Privilege Manager system extension has been unloaded, but cannot be removed completely until the system is restarted."
if [[ $INTERACTIVEMODE == yes ]]; then
  while true; do
    read -p "Restart now [Y/N]? " yn
    case $yn in
        [Yy]* ) break;;
        [Nn]* ) exit;;
        * ) echo "Please answer Y or N.";;
    esac
  done
fi

echo "Rebooting..."
/usr/bin/osascript -e 'tell app "System Events" to restart'

exit 0
