#!/bin/sh
# 18.0.1.35
KAV_APP_PKG="/Library/Application Support/Kaspersky Lab/KAV/Data/kav_app.tar.gz"
DRIVERS_PKG_DIR="/Library/Application Support/Kaspersky Lab/KAV/Data"
DRIVERS_CACHE_DIR="/Library/Application Support/Kaspersky Lab/KAV/Bases/Cache"
BASES_KLAVA_DIR="/Library/Application Support/Kaspersky Lab/KAV/Bases/KLAVA"
KAV_DATA_DIR="/Library/Application Support/Kaspersky Lab/KAV/Data"
KAV_AGENT_PKG="/Library/Application Support/Kaspersky Lab/KAV/Data/kav_agent.tar.gz"
KAV_AGENT_APP_PATH="/Library/Application Support/Kaspersky Lab/KAV/Applications/Kaspersky Anti-Virus Agent.app"
KAV_AGENT_WATCHPATH="/Library/Application Support/Kaspersky Lab/KAV/kickstart_gui"
LAUNCHAGENT_KAV_PLIST="/Library/LaunchAgents/com.kaspersky.kav.gui.plist"
DEFAULT_KAVAPP_PATH="/Applications/Kaspersky Anti-Virus For Mac.app"
UPDATE_CFG_SCRIPT="/Library/Application Support/Kaspersky Lab/KAV/Binaries/update_cfg.pl"
UPDATE_CFG_TARGET="/Library/Application Support/Kaspersky Lab/KAV/Binaries/config.xml"
add_new_environment_key()
{
python -c """
import xml.etree.ElementTree as ET
tree = ET.parse('$UPDATE_CFG_TARGET')
root = tree.getroot()
newNode = ET.Element(\"tSTRING\", name=\"$1\")
newNode.text = \"$2\"
for node in root.findall(\".//key[@name='environment']\"):
alreadyHasNode = False
for childNode in node.findall(\".//tSTRING[@name='$1']\"):
alreadyHasNode = True
if not alreadyHasNode:
print('adding $1 with value $2 to config.xml')
node.append(newNode)
tree.write('$UPDATE_CFG_TARGET')
"""
}
get_environment_key()
{
python -c """
import xml.etree.ElementTree as ET
tree = ET.parse('$UPDATE_CFG_TARGET')
root = tree.getroot()
for node in root.findall(\".//key[@name='environment']\"):
for childNode in node.findall(\".//tSTRING[@name='$1']\"):
print(childNode.text)
"""
}
apply_hotfix()
{
# Set ProductHotfix and ProductHotfixNew in integrated build
if [ ! -f "$KAV_DATA_DIR"/blregistry.xml ]
then
# TODO: any better way to do this at runtime?
echo "" > "$KAV_DATA_DIR"/blregistry.xml
fi
python -c """
import xml.etree.ElementTree as ET
tree = ET.parse('$KAV_DATA_DIR/blregistry.xml')
root = tree.getroot()
for node in root.findall(\".//*[data]/data\"):
node.set('ProductHotfix', '$1')
node.set('ProductHotfixNew', '$1')
tree.write('$KAV_DATA_DIR/blregistry.xml')
"""
}
stop_kav_app()
{
KAVAPP_RECORD=$(ps -axwo pid,command | grep -v grep | grep "Contents/MacOS/kav_app")
KAVPID=$(/bin/echo -n "$KAVAPP_RECORD" | awk '{print $1}')
if [ "$KAVPID" != "" ]
then
RELAUNCH_KAVAPP_PATH=$(/bin/echo -n "$KAVAPP_RECORD" | sed 's/[ ]*'"$KAVPID"'[ ]*\(.*\.app\).*/\1/')
kill -s KILL "$KAVPID"
fi
}
stop_kav_agent()
{
KAVPID=$(ps -axwo pid,command | grep -v grep | grep "Contents/MacOS/kav_agent" | awk '{print $1}')
if [ "$KAVPID" != "" ]
then
kill -s KILL $KAVPID
RESTART_KAVAGENT=1
fi
}
if [ "$1" != "OnHotfixInstalled" ]; then
PRODUCT_TYPE=$(get_environment_key "ProductType")
echo "ProductType = $PRODUCT_TYPE"
if [ -f "$UPDATE_CFG_SCRIPT" ]
then
echo ""
echo "Stopping application..."
stop_kav_app
# /usr/bin/perl -- "$UPDATE_CFG_SCRIPT" "$UPDATE_CFG_TARGET" "environment:MoreFromLink" "http://redirect.kaspersky.com/sales?type=moreproducts&[CommonRedirectorParams]"
# /usr/bin/perl -- "$UPDATE_CFG_SCRIPT" "$UPDATE_CFG_TARGET" "environment:CommonRedirectorParams" "act-pid=[productType]mac&act-pv=[applicationVersion]&hl=[localization]&act-serial=[keySerialNumber]&lic-id=[licenseId]&act-liccount=[act-liccount]&act-lic-type=[licenseType]&act-lic-lifespan=[licenseTerm]&act-lic-daystillexpiration=[licenseDaysToExpiration]&act-lic-dayssinceinstall=[licenseDaysSinceActivation]&act-lic-dse=[licenseDaysAfterExpiration]&act-lic-status=[licenseStatus]&kasperskyid=[kasperskyId]&ppcs-id=[ppcsId]&act-item=[ActionUIControlName]&rpe=1"
echo ""
echo "Stopping possibly respawned application..."
stop_kav_app
fi
if [ "$KAV_APP_PKG" != "" ]
then
if [ -e "$KAV_APP_PKG" ]
then
# Extract kav_app into temp folder
KAV_APP_EXTRACTION_TEMP_PATH=$(mktemp -d)
echo ""
echo "Extracting $KAV_APP_PKG into $KAV_APP_EXTRACTION_TEMP_PATH"
tar -xzvf "$KAV_APP_PKG" -C "$KAV_APP_EXTRACTION_TEMP_PATH"
echo "Extracted: "
ls -la "$KAV_APP_EXTRACTION_TEMP_PATH"
echo ""
echo "Deploying application resources..."
KAVAPP_PATHS=$(mdfind "kMDItemCFBundleIdentifier == 'com.kaspersky.kav'" | grep -v "^/Volumes/")
if [ "$KAVAPP_PATHS" == "" ]
then
KAVAPP_PATHS="$DEFAULT_KAVAPP_PATH"
fi
OLD_IFS="$IFS"
IFS=$'\n'
for KAVAPP_PATH in $KAVAPP_PATHS
do
echo ""
# Get localizations list inside bundle
BUNDLE_LOCS_LIST=$(find "$KAVAPP_PATH"/Contents/Resources/ -type d -name *.lproj -maxdepth 1 | sed 's/^.*\/\(.*\)\.lproj/\1/g' | sort | paste -sd "_" -)
echo "Bundle $KAVAPP_PATH localizations are: $BUNDLE_LOCS_LIST"
MATCHED_KAV_APP_PKG="${PRODUCT_TYPE}_${BUNDLE_LOCS_LIST}.tar.gz"
echo "Will look for $MATCHED_KAV_APP_PKG to apply patch"
# Match available archive
if [ -f "$KAV_APP_EXTRACTION_TEMP_PATH/$MATCHED_KAV_APP_PKG" ]; then
# Extract archive into bundle
echo "Extracting application resources from $MATCHED_KAV_APP_PKG to $KAVAPP_PATH..."
tar -xzvf "$KAV_APP_EXTRACTION_TEMP_PATH/$MATCHED_KAV_APP_PKG" -C "$KAVAPP_PATH"
touch "$KAVAPP_PATH"
else
echo "No matched archive in $KAV_APP_EXTRACTION_TEMP_PATH, do not apply patch for $KAVAPP_PATH"
fi
done
IFS="$OLD_IFS"
echo ""
echo "Stopping application..."
stop_kav_app
fi
fi
# TODO: Implement same patch apply logic for agent
if [ "$KAV_AGENT_PKG" != "" ]
then
if [ -e "$KAV_AGENT_PKG" ]
then
echo ""
echo "Extracting agent resources to $KAV_AGENT_APP_PATH..."
tar -xzvf "$KAV_AGENT_PKG" -C "$KAV_AGENT_APP_PATH"
touch "$KAV_AGENT_APP_PATH"
echo ""
echo "Stopping agent..."
stop_kav_agent
if [ "$RESTART_KAVAGENT" == "1" ]
then
AGENTPID=$(ps -axwo pid,command | grep -v grep | grep "Contents/MacOS/kav_agent" | awk '{print $1}')
if [ "$AGENTPID" == "" ]
then
echo ""
echo "Restarting agent..."
LOGINWINDOW_RECORDS=$(ps -axwo pid,uid,command | grep -v grep | grep loginwindow)
for RECORD in "$LOGINWINDOW_RECORDS"
do
LOGINWINDOW_PID=$(/bin/echo -n "$RECORD" | awk '{print $1}')
LOGINWINDOW_UID=$(/bin/echo -n "$RECORD" | awk '{print $2}')
echo "Loading launch agent for uid $LOGINWINDOW_UID..."
launchctl asuser "$LOGINWINDOW_UID" launchctl load "$LAUNCHAGENT_KAV_PLIST"
done
echo "Kickstarting agent..."
touch "$KAV_AGENT_WATCHPATH"
fi
fi
fi
fi
fi
split_driver_version()
{
MAJOR=$(echo $1 | sed -n "s/\([0-9]*\).*/\1/p")
MINOR=$(echo $1 | sed -n "s/\([0-9]*\)\.\([0-9]*\).*/\2/p")
BUGFIX=$(echo $1 | sed -n "s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/p")
STAGE=$(echo $1 | sed -n "s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\([a-z]*\).*/\4/p")
BUILD=$(echo $1 | sed -n "s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\([a-z]*\)\([0-9]*\)/\5/p")
echo "$MAJOR $MINOR $BUGFIX $STAGE $BUILD"
}
get_driver_version_component()
{
echo "$1" | cut -f $2 -d " "
}
get_driver_version_stage_priority()
{
PRIORITIZED_LIST=$(echo ":d"; echo ":a"; echo ":b"; echo ":fc"; echo ":")
echo "$PRIORITIZED_LIST" | grep -n "^:$1" | sed "s/\([0-9]*\).*/\1/"
}
compare_driver_versions()
{
V1=$(split_driver_version $1)
V2=$(split_driver_version $3)
N1=$(echo "$V1" | awk '{ print NF }')
N2=$(echo "$V2" | awk '{ print NF }')
local N
if [ $N1 -gt $N2 ]; then
N=$N1
else
N=$N2
fi
for i in `seq 1 $N`; do
local NUMBER1=$(get_driver_version_component "$V1" $i);
local NUMBER2=$(get_driver_version_component "$V2" $i);
if [ $i -eq 4 ]; then
NUMBER1=$(get_driver_version_stage_priority ${NUMBER1})
NUMBER2=$(get_driver_version_stage_priority ${NUMBER2})
fi
if [ ${NUMBER1:=0} -ne ${NUMBER2:=0} ]; then
[ ${NUMBER1:=0} $2 ${NUMBER2:=0} ]
return
fi
done
[ 0 $2 0 ]
}
update_driver()
{
[ ! -f "$5/$3" ] && return 1
DRIVER_REFERENCES_PATH="/Library/Application Support/Kaspersky Lab/Shared/$1.references"
DRIVER_REFERENCES_LEGACY_PATH="$4/$1.kext/Contents/.References.plist"
if [ "$4" == "/Library/Extensions" ] && [ -f "$DRIVER_REFERENCES_LEGACY_PATH" ] && [ ! -f "$DRIVER_REFERENCES_PATH" ]; then
DRIVER_REFERENCES_DIR=$(dirname "$DRIVER_REFERENCES_PATH")
mkdir -p "$DRIVER_REFERENCES_DIR"
mv "$DRIVER_REFERENCES_LEGACY_PATH" "$DRIVER_REFERENCES_PATH" || return 1
fi
if [ "$4" == "/System/Library/Extensions" ] && [ -f "$DRIVER_REFERENCES_LEGACY_PATH" ]; then
rm -rf "$DRIVER_REFERENCES_LEGACY_PATH"
fi
DRIVER_PATH="$4/$1.kext"
if [ -d "$DRIVER_PATH" ]; then
INSTALLED_DRIVER_VERSION=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$DRIVER_PATH/Contents/Info.plist")
compare_driver_versions $2 -gt $INSTALLED_DRIVER_VERSION || return 1
fi
rm -rf "$DRIVER_PATH"
tar -xzvf "$5/$3" -C "$4"
chown -R root:wheel "$DRIVER_PATH"
echo "Driver $1 updated to version $2"
}
echo "Copy mark and kimul to /Library/Extensions"
copy_kext_if_needed()
{
echo "copy_kext_if_needed for $1 $2"
if [ ! -d /Library/Extensions/$1.kext ]; then
KLAVA_LOGS=$(ls -1 "$BASES_KLAVA_DIR"/log* | sort -r)
OLD_IFS=$IFS
IFS='
'
for LOG in $KLAVA_LOGS; do
FOUND=0
echo "$LOG found, try find $1 here..."
LOGPATH="$LOG"
LOGMOUNTPATH=/tmp/kl_log_kdb_mount
LOGISOPATH=/tmp/kl_log_kdb.iso
ln -s "$LOGPATH" "$LOGISOPATH"
hdiutil attach -nobrowse "$LOGISOPATH" -mountpoint "$LOGMOUNTPATH"
if [ -f "$LOGMOUNTPATH"/$1.signed.tar.gz ]; then
archive_name=$(basename "$(ls -1 "$LOGMOUNTPATH"/$1.signed.tar.gz)")
echo "$archive_name found in Bases/Cache, try copy to /Library/Extensions..."
update_driver $1 $2 "$archive_name" /Library/Extensions "$LOGMOUNTPATH"
FOUND=1
fi
hdiutil detach "$LOGMOUNTPATH"
rm "$LOGISOPATH"
if [ "$FOUND" == 1 ]; then
break
fi
done
IFS=$OLD_IFS
else
echo "$1.kext is already in /Library/Extensions"
fi
}
copy_kext_if_needed kimul 46
copy_kext_if_needed mark 1.0.6
echo "Updating drivers..."
SHOULD_RESET_DRIVER_CACHE=0
update_driver klif 3.6.9a45 klif.signed.tar.gz /Library/Extensions "$DRIVERS_PKG_DIR" && SHOULD_RESET_DRIVER_CACHE=1
# update_driver klnke 2.3.1a8 klnke.signed.tar.gz /Library/Extensions "$DRIVERS_PKG_DIR" && SHOULD_RESET_DRIVER_CACHE=1
if [ "$SHOULD_RESET_CACHE" == "1" ]; then
echo "Reseting driver cache..."
touch "/Library/Extensions"
fi
echo "Update config.xml with EulaFile key"
UPDATE_CFG_TARGET_copy="/tmp/config.xml.tmp"
awk ' {print $0}; /environment/ { print "\t\t'%%Localization%%'" }' "$UPDATE_CFG_TARGET" > "$UPDATE_CFG_TARGET_copy"
mv -v "$UPDATE_CFG_TARGET_copy" "$UPDATE_CFG_TARGET"
chmod -R o+r "/Library/Application Support/Kaspersky Lab/KAV/Bases/"
rm -rf /Library/Caches/com.kaspersky.kav/PersonalCertificates/*