#!/bin/bash

# Script freely provided by Bill Landry (bill@inetmsg.com).
#
# Version 1.6 (updated 8/27/07)
#   - Added support for SecurityInfo and Malware Black List
#     signature file downloads.
#   - Changed the script name from ss-msrbl.sh to unofficial-sigs.sh
#     since there are now 4 different signature providers supported.
#   - Since the MBL signatures are dynamically created and therefor
#     cannot be checked for change before downloading, a variable was
#     added so that a specific download time interval can be set (see
#     the "USER EDIT SECTION" below).
#   - Added signature file download time randomization (to disable
#     randomization, see the "USER EDIT SECTION" below for details).
#
# Version 1.5 (updated 8/17/07 - Thanks to Dan Larsson for his
# contributions to this update)
#   - Added separate variable for ClamAV group ID for setting
#     appropriate file group access permissions.
#   - Added variables for signature file update URLs.
#   - Added support for automatic reloading of signature
#     databases when updates are found.
#
# Version 1.4 (updated 7/13/07)
#   - Added checks to verify that the signature files exist,
#     and if not, do an initial download, decompress and test.
#   - Added variables for clamav signatures location path and
#     clamd user account (the account that clamd runs under).
#   - Added/modified script comments.
#
# Version 1.3
#   - Added checks to either confirm the existence of the
#     temporary working directories or to create them.
#   - Changed "cp --reply=yes" to "cp -f".  If this
#     causes problems with older versions of "cp",
#     you will need to change it back.
#
# Version 1.2
#   - Repointed URLs for SaneSecurity downloads to
#     the new mirror redirect links.
#
# Version 1.1
#   - Converted MSRBL downloads from curl to rsync.
#
# Version 1.0 (initial script created).

####################################################################
# SCRIPT USER EDIT SECTION - SET PROGRAM PATHS AND OTHER VARIABLES #
####################################################################

# Edit quoted variables below to meet your own particular
# needs/requirements, but do not remove the "quote" marks.

# Set and export program paths.
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
export PATH

# Set path to clamd.pid file (see clamd.conf for path location).
# To disable automatic signature database reloading, comment out
# the next line.
clamd_pid="/var/run/clamd/clamd.pid"

# Set path to ClamAV signature files location.
clam_sigs="/var/lib/clamav"

# Set ClamD user and group accounts.
clam_user="clamav"
clam_group="clamav"

# Set temp working directory paths (edit to meet your own needs).
tmp_dir="/var/tmp/clamdb"
rsync_dir="/var/tmp/rsync"

# Enable or disable random download execution.  This allows the script
# to be executed via cron, but actual signature downloads will randomly
# start between 1 and 10 minutes after execution.  This helps to more
# evenly distribute load on the download sites.  To disable, set the
# following variable to "no".  Randomization is automatically disabled
# if the "bash" shell is not located on your system.  If you wish to 
# use download randomization, install bash and keep the following
# variable set to "yes".  Otherwise, simply disregard this section.
enable_random="yes"

# SaneSecurity source URLs - *MUST* be HTTP URLs, one URL per line.
# Add/remove/modify URLs between quote makes as needed.  To disable
# SaneSecurity downloads, comment out the next four lines.
ss_urls="
   http://www.sanesecurity.com/clamav/phishsigs/phish.ndb.gz
   http://www.sanesecurity.com/clamav/scamsigs/scam.ndb.gz
"

# MSRBL source URLs - *MUST* be RSYNC URLs, one URL per line.
# Add/remove/modify URLs between quote marks as needed.  To
# disable MSRBL downloads, comment out the next four lines.
msrbl_urls="
   rsync://rsync.mirror.msrbl.com/msrbl/MSRBL-Images.hdb
   rsync://rsync.mirror.msrbl.com/msrbl/MSRBL-SPAM.ndb
"

# SecurityInfo source URLs - *MUST* be HTTP URLs, one URL per line.
# Add/remove/modify URLs between quote makes as needed.  To disable
# SecurityInfo downloads, comment out the next three lines.
si_url="
   http://clamav.securiteinfo.com/vx.hdb.gz
"

# Malware Black List source URLs - *MUST* be HTTP URLs, one URL per
# line.  Add/remove/modify URLs between quote makes as needed.  To
# disable Malware BL downloads, comment out the next three lines.
mbl_url="
   http://www.malware.com.br/cgi/submit?action=list_clamav
"

# Since the Malware Black List signature file is dynamically created
# via CGI, the file must be named when downloaded (change the file
# name to your own liking, but the file extension must remain .db).
mbl_file="mbl.db"

# Since the Malware Black List signature file is dynamically created,
# there is no way to test for changes prior to downloading.  For this
# reason, you will need to set a reasonable time interval in "hours"
# for MBL signature file downloads.  As shown below, this has been
# set to update every "6" hours, which seems appropriate (that's 4
# updates per day - change only if you REALLY feel you must.  However,
# I would not suggest going below every 4 hour lest you risk being
# blacklisted by the MBL site).
mbl_update_hours="6"

################################################################################
# END OF SCRIPT USER EDIT SECTION - YOU SHOULD NOT NEED TO EDIT ANYTHING BELOW #
################################################################################

# Check to see if the working directories shown above were created.
# If not, create them.  Otherwise, ignore and proceed with script.
mkdir -p $tmp_dir $rsync_dir

# Change shell to the ClamAV signature files directory.
cd $clam_sigs

# Signature download time randomization section.  This section is
# automatically disabled if "bash" is not found on the system.
bash=`which bash 2> /dev/null`
if [ $enable_random == yes -a -f "$bash" ]
   then
      seconds=$[ ($RANDOM % 60) * 10 ]
      let "seconds %= 600"
   if [ $seconds -lt 60 ] ; then
      seconds=`expr $seconds + 60`
   fi
      echo ""
      echo "`date` - Pausing signature file updates for $seconds seconds..."
      sleep $seconds
      echo ""
      echo "`date` - Pause complete, checking for new signature files..."
   else
      echo "Randomization disabled, either intentionally or because the bash shell"
      echo "was not found on your system - now checking for new signature files..."
fi

# Download Malware Black List (MBL) signature file every set number
# of hours (as configured in the "User Edit" section above). Since
# the signatures are dynamically created via CGI, there is no way
# to compare it to the existing file to determine if it has changed.
# We run this update first in order to get an acurate timestamp in
# case any other updates cause delays due to site access issues.
for source_url in $mbl_url ; do
   echo ""
   echo "========================================"
   echo "Malware Black List Signature File Update"
   echo "========================================"
   echo ""
   if [ ! -s $mbl_file ]
      then
         curl -R -o $tmp_dir/$mbl_file $source_url
         test -s $tmp_dir/$mbl_file && \
            clamscan --quiet -d $tmp_dir/$mbl_file - < /dev/null && \
            mv -f $tmp_dir/$mbl_file . && \
            do_clamd_reload=1
         [ `date +%s > $clam_sigs/last-mbl-update.txt` ]
         echo ""
   fi
   if [ ! -s  $clam_sigs/last-mbl-update.txt ]
      then
         [ `date +%s > $clam_sigs/last-mbl-update.txt` ]
         update_interval=`expr $mbl_update_hours \* 3600`
         current_time=`date +%s`
         lastupdate_time=`cat $clam_sigs/last-mbl-update.txt`
         time_interval=`expr $current_time - $lastupdate_time`
      else
         update_interval=`expr $mbl_update_hours \* 3600`
         current_time=`date +%s`
         lastupdate_time=`cat $clam_sigs/last-mbl-update.txt`
         time_interval=`expr $current_time - $lastupdate_time`
   fi
   # Deduct 600 seconds (10 minutes) from the update interval in
   # order to compensate for timing anomalies and/or script delays.
   if [ $time_interval -ge `expr $update_interval - 600` ]
      then
         curl -R -o $tmp_dir/$mbl_file $source_url
         test -s $tmp_dir/$mbl_file && \
            clamscan --quiet -d $tmp_dir/$mbl_file - < /dev/null && \
            cp -f $mbl_file $mbl_file-bak && \
            mv -f $tmp_dir/$mbl_file . && \
            do_clamd_reload=1
         [ `date +%s > $clam_sigs/last-mbl-update.txt` ]
      else
         time_remaining=`expr $update_interval - $time_interval`
         hours_left=`expr $time_remaining / 3600`
         minutes_left=`expr $time_remaining % 3600 / 60`
         echo "$mbl_update_hours hours have not yet elapsed since the last MBL"
         echo "update - no update was performed at this time."
         echo ""
         echo "Next MBL update will be performed in $hours_left hour(s), $minutes_left minute(s)"
   fi
done

# Check for existing SaneSecurity signature files.  If they exist, then run
# the update checks.  Otherwise, just download, extract and test the files.
for source_url in $ss_urls ; do
   source_file=`basename $source_url`
   target_file=`basename $source_url .gz`
   echo ""
   echo "============================================"
   echo "SaneSecurity $target_file Signature File Update"
   echo "============================================"
   echo ""
   if [ ! -s $target_file ]
      then
         curl -L -R -o $tmp_dir/$source_file $source_url
         test -s $tmp_dir/$source_file && \
            gunzip -cdf $tmp_dir/$source_file > $tmp_dir/$target_file && \
            clamscan --quiet -d $tmp_dir/$target_file - < /dev/null && \
            mv -f $tmp_dir/$target_file $tmp_dir/$source_file . && \
            do_clamd_reload=1
      else
         curl -L -R -z $source_file -o $tmp_dir/$source_file $source_url
         test -s $tmp_dir/$source_file && \
            gunzip -cdf $tmp_dir/$source_file > $tmp_dir/$target_file && \
            clamscan --quiet -d $tmp_dir/$target_file - < /dev/null && \
            cp -f $target_file $target_file-bak && \
            mv -f $tmp_dir/$target_file $tmp_dir/$source_file . && \
            do_clamd_reload=1
   fi
done

# Check for existing MSRBL signature files.  If they exist, then run the
# update checks.  Otherwise, just download, extract and test the files.
for source_url in $msrbl_urls ; do
   target_file=`basename $source_url`
   echo ""
   echo "============================================"
   echo "MSRBL $target_file Signature File Update"
   echo "============================================"
   if [ ! -s $target_file ]
      then
         rsync -t --stats $source_url $rsync_dir/$target_file
         cp -p $rsync_dir/$target_file $tmp_dir && \
            test -s $tmp_dir/$target_file && \
            clamscan --quiet -d $tmp_dir/$target_file - < /dev/null && \
            mv -f $tmp_dir/$target_file . && \
            do_clamd_reload=1
      else
         rsync -tu --stats $source_url $rsync_dir/$target_file
         test $rsync_dir/$target_file -nt $target_file && \
            cp -p $rsync_dir/$target_file $tmp_dir && \
            test -s $tmp_dir/$target_file && \
            clamscan --quiet -d $tmp_dir/$target_file - < /dev/null && \
            cp -f $target_file $target_file-bak && \
            mv -f $tmp_dir/$target_file . && \
            do_clamd_reload=1
   fi
done

# Check for an existing SecurityInfo VX signature file.  If it exists, then
# run the update check.  Otherwise, just download, extract and test the file.
for source_url in $si_url ; do
   source_file=`basename $source_url`
   target_file=`basename $source_url .gz`
   echo ""
   echo "========================================="
   echo "SecurityInfo $target_file Signature File Update"
   echo "========================================="
   echo ""
   if [ ! -s $target_file ]
      then
         curl -L -R -o $tmp_dir/$source_file $source_url
         test -s $tmp_dir/$source_file && \
            gunzip -cdf $tmp_dir/$source_file > $tmp_dir/$target_file && \
            clamscan --quiet -d $tmp_dir/$target_file - < /dev/null && \
            mv -f $tmp_dir/$target_file $tmp_dir/$source_file . && \
            do_clamd_reload=1
      else
         curl -L -R -z $source_file -o $tmp_dir/$source_file $source_url
         test -s $tmp_dir/$source_file && \
            gunzip -cdf $tmp_dir/$source_file > $tmp_dir/$target_file && \
            clamscan --quiet -d $tmp_dir/$target_file - < /dev/null && \
            cp -f $target_file $target_file-bak && \
            mv -f $tmp_dir/$target_file $tmp_dir/$source_file . && \
            do_clamd_reload=1
   fi
done

# Set appropriate file access permissions
chown -R $clam_user:$clam_group $clam_sigs

# Remove any leftover files in the $tmp_dir working directory (this
# should only happen if a corrupted signature file is detected)
rm -f $tmp_dir/*

# Reload all clamd signature databases if updates detected and
# neither $clamd_pid nor $do_clamd_reload are null.
if [ -n "$clamd_pid" -a -n "$do_clamd_reload" ] ; then
   echo ""
   echo "=============================================="
   echo "Update(s) detected, reloading ClamAV databases"
   echo "=============================================="
   kill -USR2 `cat $clamd_pid`
fi

exit $?

