#!/bin/zsh

# MARK: Usage, params

SERVER_SHARE=""
USER=""
PWD=""
REMOTE_FILE=""

usage() {
	cat << EOF
This script copies files required to make SSL scanning work on endpoints.
If EES product v 9+ is already installed, script stops the protection,
copies the required files into place and starts the protection again.
If product is not installed, these files are placed into a folder
and during install, they will be copied to the correct folder.
Usage: $(basename $0) -s SERVER_SHARE -u USER -p PASSWORD -f ZIP_FILE_NAME
	-s  Server share path (required)
	-u  Username (required)
	-p  Password (required)
	-f  File name (required)
	-h  Display this help message
EOF
	exit 1
}

check_sudo() {
	if ! /usr/bin/id -u &>/dev/null || [ $(/usr/bin/id -u) -ne 0 ]; then
		echo "Error: This script must be run with sudo privileges"
		echo "Current user ID: $(/usr/bin/id -u)"
		exit 1
	fi
}

# Parse command line arguments
while getopts "s:u:p:f:h" opt; do
	case $opt in
		s)
			SERVER_SHARE=$OPTARG
			;;
		u)
			USER=$OPTARG
			;;
		p)
			PWD=$OPTARG
			;;
		f)
			REMOTE_FILE=$OPTARG
			;;
		h)
			usage
			;;
		\?)
			echo "Invalid option: -$OPTARG"
			usage
			;;
		:)
			echo "Option -$OPTARG requires an argument"
			usage
			;;
	esac
done

if [[ -z $SERVER_SHARE ]] || [[ -z $USER ]] || [[ -z $PWD ]] || [[ -z $REMOTE_FILE ]]; then
	echo "Error: Missing required parameters"
	usage
fi

check_sudo

# MARK: Cleanup

cleanup_folders() {
	# Unmount if mounted
	if mount | grep -q "${MOUNT_POINT}"; then
		umount -f "${MOUNT_POINT}" 2>/dev/null
	fi
	# Remove mount temporary directory if it exists
	if [[ -d "${MOUNT_POINT}" ]]; then
		rmdir "${MOUNT_POINT}" 2>/dev/null
	fi
}

cleanup_password() {
	unset PWD
	unset ENCODED_PWD
	unset USER
	unset ENCODED_USER
	unset SERVER_SHARE
}

cleanup() {
	cleanup_folders
	cleanup_password
}

trap cleanup EXIT INT TERM

# MARK: Prepare mount points, paths

readonly MOUNT_POINT="/Volumes/smb_mount_$$"
readonly IMPORT_PATH="/Library/Application Support/ESET/Security/CertImport"

cleanup_folders
if ! mkdir -p "${MOUNT_POINT}"; then
	echo "Error: Failed to create mount point directory ${MOUNT_POINT}"
	exit 1
fi

if [[ -d "${IMPORT_PATH}" ]]; then
	rm -rf "${IMPORT_PATH}"
fi

install -d -m 600 -o root -g wheel "${IMPORT_PATH}"

echo "Mount point: ${MOUNT_POINT}"

#MARK: Percent-encode the username and password
encode_string() {
    local string="$1"
    string="${string//\%/%25}"  # %
    string="${string// /%20}"   # Space
    string="${string//\//%2F}"  # Forward slash
    string="${string//\@/%40}"  # @
    string="${string//\:/%3A}"  # :
    string="${string//\&/%26}"  # &
    string="${string//\?/%3F}"  # ?
    string="${string//\+/%2B}"  # +
    string="${string//\#/%23}"  # #
    string="${string//\\/%5C}"  # Backslash
    string="${string//\"/%22}"  # Double quote
    string="${string//\'/%27}"  # Single quote
    echo "$string"
}

ENCODED_USER=$(encode_string "$USER")
ENCODED_PWD=$(encode_string "$PWD")

# MARK: SMB mount. Change to different FS if you wish

# Mount the SMB share. If you wish to use different file transfer method, change the lines below
echo "Mounting SMB share..."
CMD="//${ENCODED_USER}:${ENCODED_PWD}@${SERVER_SHARE}/"
mount_smbfs "${CMD}" "${MOUNT_POINT}"

if [[ $? -ne 0 ]]; then
	echo "Error: Failed to mount SMB share. Please check your server, share name, username, and password."
	exit 1
fi

# MARK: Copy files. Prepare CertImport folder for future installation.

echo "Copying file..."
if [[ ! -f "${MOUNT_POINT}/${REMOTE_FILE}" ]]; then
	echo "Error: File ${MOUNT_POINT}/${REMOTE_FILE} does not exist"
	exit 1
fi
cp -f "${MOUNT_POINT}/${REMOTE_FILE}" "${IMPORT_PATH}"

# Check if download was successful
if [[ -f "${IMPORT_PATH}/${REMOTE_FILE}" ]]; then
	echo "File successfully downloaded to ${IMPORT_PATH}"
else
	echo "Error: File download failed"
	exit 1
fi

unzip -o "${IMPORT_PATH}/${REMOTE_FILE}" -d "${IMPORT_PATH}"
rm -rf "${IMPORT_PATH}/${REMOTE_FILE}"

readonly PROTOCIPHERKEY="protoscanCipherKey.bin"
readonly PROTOROOTCERT="protoscanRootCert.crt"
readonly PROTOROOTKEY="protoscanRootKey.bin"

readonly PROTOCIPHERKEY_IMPORT="${IMPORT_PATH}/${PROTOCIPHERKEY}"
readonly PROTOROOTCERT_IMPORT="${IMPORT_PATH}/${PROTOROOTCERT}"
readonly PROTOROOTKEY_IMPORT="${IMPORT_PATH}/${PROTOROOTKEY}"

# $1: owner
# $2: permissions
# $3: filename
function set_owner_perm() {
	if ! chown "$1" "$3"; then
		echo "Error: Failed to set owner $1 for file $3"
		exit 1
	fi

	if ! chmod "$2" "$3"; then
		echo "Error: Failed to set perm $2 for file $3"
		exit 1
	fi
}

if [[ -f "${PROTOCIPHERKEY_IMPORT}" && -f "${PROTOROOTCERT_IMPORT}" && -f "${PROTOROOTKEY_IMPORT}" ]]; then
	set_owner_perm "root:wheel" "600" "${PROTOCIPHERKEY_IMPORT}"
	set_owner_perm "root:wheel" "600" "${PROTOROOTCERT_IMPORT}"
	set_owner_perm "root:wheel" "600" "${PROTOROOTKEY_IMPORT}"
else
	echo "Error: Files missing from import folder, were they extracted correctly?"
	exit 1
fi

# MARK: If product running already has SSL functionality (v. 9+), move files to cache/data

if ! VERSION=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "/Applications/ESET Endpoint Security.app/Contents/Info.plist" 2>&1); then
	echo "Files succesfully copied and ready for product install - no EES product detected"
	exit 0
fi

readonly MAJOR_VERSION=${VERSION%%.*}
if [[ "$MAJOR_VERSION" =~ ^[0-9]+$ && $MAJOR_VERSION -lt 9 ]]; then
	echo "Files succesfully copied and ready for product install - EES product version $VERSION"
	exit 0
fi

readonly NETPROTD_USER="eset-ecsm-netprotd"
readonly DAEMONS_GROUP="eset-ecsm-daemons"

if ! dscl . -read /Users/${NETPROTD_USER} > /dev/null 2>&1; then
	echo "Error: User ${NETPROTD_USER} does not exist, product installation damaged"
	exit 1
fi

if ! dscl . -read /Groups/${DAEMONS_GROUP} > /dev/null 2>&1; then
	echo "Error: Group ${DAEMONS_GROUP} does not exist, product installation damaged"
	exit 1
fi

if ! launchctl bootout system /Library/LaunchDaemons/com.eset.protection.plist; then
	if [[ $? -eq 5 ]]; then #5 equals to input/output error, which usually means that plist is not loaded
		echo "Warning: Protection plist is not loaded, continuing..."
	else
		echo "Error: Couldn't bootout protection plist. Please uninstall the product and run the script before installation."
		exit 1
	fi
fi

echo "Version is 9 or greater (${VERSION%%.*}), continue"
readonly LOCAL_PATH="/Library/Application Support/ESET/Security/cache/data"
if [[ -d "${LOCAL_PATH}" ]]; then
	rm -f "${LOCAL_PATH}/endCertKeys.bin"
	rm -rf "${LOCAL_PATH}/protoscan"
	rm -rf "${LOCAL_PATH}/sslmodule"
else
	echo "Error: path $LOCAL_PATH does not exist, product installation damaged?"
	exit 1
fi

echo "Old proto files removed from local path ${LOCAL_PATH}"

readonly PROTOCIPHERKEY_LOCAL="${LOCAL_PATH}/${PROTOROOTKEY}"
readonly PROTOROOTCERT_LOCAL="${LOCAL_PATH}/${PROTOROOTCERT}"
readonly PROTOROOTKEY_LOCAL="${LOCAL_PATH}/${PROTOROOTKEY}"

# MARK: copy files to cache/data and set their owner/permissions

rm -f "${PROTOCIPHERKEY_LOCAL}"
rm -f "${PROTOROOTCERT_LOCAL}"
rm -f "${PROTOROOTKEY_LOCAL}"
if [[ -f "${PROTOROOTKEY_LOCAL}" && -f "${PROTOROOTCERT_LOCAL}" && -f "${PROTOCIPHERKEY_LOCAL}" ]]; then
	echo "Error: Files were not removed correctly, please re-run the script or uninstall the product and run the script before the product is installed"
	exit 1
fi

echo "Proto files removed from local path ${LOCAL_PATH}"

cp -f "${PROTOCIPHERKEY_IMPORT}" "${LOCAL_PATH}"
cp -f "${PROTOROOTCERT_IMPORT}" "${LOCAL_PATH}"
cp -f "${PROTOROOTKEY_IMPORT}" "${LOCAL_PATH}"

if [[ -f "${PROTOROOTKEY_LOCAL}" && -f "${PROTOROOTCERT_LOCAL}" && -f "${PROTOCIPHERKEY_LOCAL}" ]]; then
	set_owner_perm "${NETPROTD_USER}:${DAEMONS_GROUP}" "600" "${PROTOROOTKEY_LOCAL}"
	set_owner_perm "${NETPROTD_USER}:${DAEMONS_GROUP}" "600" "${PROTOROOTCERT_LOCAL}"
	set_owner_perm "${NETPROTD_USER}:${DAEMONS_GROUP}" "600" "${PROTOCIPHERKEY_LOCAL}"
else
	echo "Error: Required files were not copied. Please re-run the script. If it fails multiple times, please uninstall the product and execute the script before product is installed."
	exit 1
fi

echo "Proto files copied to local path ${LOCAL_PATH}"

if ! launchctl bootstrap system /Library/LaunchDaemons/com.eset.protection.plist; then
	echo "Error: Couldn't bootstrap protection plist, manual fix required! Please bootstrap the ESET protection plist or re-install the product."
	exit 1
fi

#cleanup done by the trap at MARK: Cleanup
echo "Done!"
