[Avcheck] automated AVP update script

Michael Kubecka mkubecka@swansystems.com
Fri, 25 Jan 2002 11:28:06 -0800


>>
Again, as I already said before, the only more-or-less reliable
way to perform updates is:

 1 download all updates to a separate directory.  Abort on any error
 2 execute kavscanner or kavdaemon with those updated bases, giving
   it a file with known virus to check.  Both should return known
   exit code.  If something goes wrong, abort.
   scanner/daemon should be executed as a separate user in this
   case, to avoid possible further damage.
 3 rename current working bases to `old' directory (erasing it's
   content if `old' already exists)
 4 rename new bases directory to be current
 5 reload (or restart) running daemon
<<

Based on several messages and snippets of code I've seen on this list, I
wrote
a script a while ago to automate AVP virus updating.  I modified it
shortly after the discussion about someone receiving a corrupted
AV update from Kaspersky's site that killed his kavdaemon.  The script
follows Michael
Tokarev's list above (except that, for right now, it runs as root. 
Shame on me.)

I run the script from cron, and it e-mails me a msg with "OK" or "ERROR"
in the
subject so I can see at a glance how things went.

The script successfully detected some problem/corruption in AV virus
defs a month
ago that continued for about 4 days, so it seems to work OK.

Hopefully the below will be helpful.  Or if anyone has changes or
suggestions,
let me know, as I'd like to improve the script where possible.

==========================================================================

#!/bin/sh
# Modified by M. Kubecka from examples
# provided by Michael Tokarev,
# Ralf Hildebrandt, Kaspersky and others on the
# avcheck list.

# Version 1.6, written for FreeBSD 4.x
# 01/04/2002

# Future mods:
# Kavscanner and kavdaemon should be executed as
# a non-root user.

PATH=$PATH:/usr/local/bin
AVP=/var/chroot/AVP
Subj="AVP Update Status - OK"

# Assumes the directory
# $AVP/test_files which contains eicar.msg
# for test virus-scanning.  The dir should be
# world readable.

# Name of mail administrator acct to receive
# status messages.

MailAdmin="root"

# defer avpcheck Transport
# The defer_transports parameter allows you to specify what
# mail should always be deferred until Postfix is
# explicitly asked to deliver. 

echo "Temporarily deferring mail..."
postconf -e "defer_transports = avpcheck"

# kill kavdaemon

echo "Killing the Kaspersky kavdaemon..."
cd $AVP
$AVP/kavdaemon -ka && sleep 2

# Save old virus definition updates
# in case of problems in updating...

echo "Saving the current anti-virus definitions..."
mkdir $AVP/Bases.old
chmod 755 $AVP/Bases.old
cp -p $AVP/Bases/* $AVP/Bases.old

# Fetch updates to temporary directory...
# (You could also use -ki instead of -kb, to get
# incremental updates.)

echo "Fetching Kaspersky virus definition updates..."
$AVP/kavupdater -y -o -kb -b=$AVP/Bases \
-ui=http://downloads1.kaspersky-labs.com/updates > /root/kavupdate.tmp
exitCode=$?

case $exitCode in
        6)
        result="(6) Found corrupted file; process stopped."
        ;;
        4)
        result="(4) Found corrupted file."
        ;;
        2)
        result="Process stopped on corrupted file."
        ;;
        0)
        result="Antiviral databases correctly loaded."
        ;;
        *)
        result="($exitCode) Unknown failure."
esac

# Don't just depend on the exit code; also check
# the output of the update process.
if [ 0 -lt $(egrep -c "(not completed|corrupted)" /root/kavupdate.tmp)
]; then
        exitCode=6
        result="(6) Found corrupted file; process stopped."
fi

records=`cat /root/kavupdate.tmp | grep 'Known' \
| sed 's/.*\. //'`

# Test the new virus definitions by scanning
# a known infected file...
if [ -f $AVP/test_files/eicar.msg -a $exitCode -eq 0 ]; then
        echo "Testing the virus defs by scanning a known-infected
file..."
        $AVP/kavscanner -T $AVP/tmp -O $AVP/test_files/eicar.msg

        virexitCode=$?
        lo=$[$virexitCode%16]
        hi=$[$virexitCode/16]

        # If it doesn't detect known virus or suspicious object
        # then we'll assume there's a problem with the defs.

        if [ $virexitCode -ne 4 -a $virexitCode -ne 3 ]; then
                echo "Known virus not detected!"
                exitCode=6
                result="(6) Found corrupted file; process stopped."
        else
                echo "Virus detected successfully."
        fi
fi

# If the virus definitions didn't load properly
# then fall back...

if [ $exitCode -ne 0 ]; then
        Subj="AVP Update Status - ERROR"
        echo "A problem was encountered during update."
        echo "Falling back to previous virus definitions..."
        rm -rf $AVP/Bases > /dev/null 2>&1
        mv $AVP/Bases.old $AVP/Bases
        records="Reverted to previous known good anti-virus
definitions."
fi

# Fix permissions.
echo "Setting permissions on anti-virus databases..."
chmod 644 $AVP/Bases/* > /dev/null
chmod 755 $AVP/Bases > /dev/null
rm -rf $AVP/Bases.old > /dev/null 2>&1

# Start kavdaemon chroot()'ed as unprivileged user avdaemon.
# The "echo no" line is needed only for the evaluation version,
# otherwise comment it out.

echo "Starting the Kaspersky kavdaemon..."

# echo no | \   # only needed for the evaluation version!
/usr/bin/env - HOME=/ \
/usr/bin/nice \
/usr/local/sbin/uchroot -u avdaemon $AVP \
./kavdaemon -dl -MP -f=/ctl /tst > /dev/null

# un-defer avpcheck Transport
echo "Undeferring mail..."
sleep 1 && postconf -e "defer_transports ="

# Send a status update to the mail administrator
currentdate=`date`
echo "$currentdate:
Kaspersky's virus definitions update status:
$result
$records" | \
mail -s "$Subj" $MailAdmin

exit $exitCode