#!/bin/sh # Settings modified for Debian by Gary V (mr88talent at yahoo dot com) # SaneSecurity downloads are temporarily disabled in this script. # Script freely provided by Bill Landry (bill@inetmsg.com); however, use # at your own peril! (:-O). Comments, suggestions, and recommendations # for improving this script are always welcome. Feel free to report any # issues, as well. # # Version 1.7d (updated 10/5/08 - Thanks to Burt Heymanson for his # contribution to this update - silence curl output) # - Added 2 new SaneSecurity signature databases: junk.ndb & rogue.hdb. # - Added a configuration option to silence curl output to only report # errors to stderr rather than all download stats. # # Version 1.7c (updated 9/25/07 - Thanks to Dennis Peterson and Jan-Perter # Cornet for the perl solution for calculating seconds since epoch) # - Added timeout values to curl and rsync downloads in order to prevent # the script from hanging on a non-responsive signature host site. # - Apparently Solaris does not support "date +%s", which calculates # the number of seconds since epoch. This date function is used to # calculate when to do MBL downloads. A perl solution has been added # as a fall-back option. If "date +%s" is not supported and perl is # not found on the system, the script will report a warning message # and skip MBL updates, but the script will continue processing other # third-party signature updates. # # Version 1.7b (updated 9/23/07) # - Changed all script "`expr ...`" interger expressions to the shell # supported "$((...))" format, which is what was being used in all # other newer sections of the script. So this change should not # pose any problems, but if it does, please let me know. # - Changed all clamscan signature file tests from using /dev/null, # which was causing an access permissions issues to the temporary # directory for some users, to a direct path to a temp test file. # # Version 1.7a (updated 9/10/07) # - Added secondary perl socket test to detect if clamd is running. # This test uses the 'IO::Socket::UNIX' perl module. If socat is # not found on the system, then the script will attempt to use the # perl module instead (the user will be warned if neither socat nor # IO::Socket::UNIX are found, but the script will still run updates). # - Added two new SecuriteInfo signature file URLs. # - Updated comments to reflect the additional perl socket test. # # Version 1.7 (updated 9/7/07) # - Added a check to see if ClamD is running or not. This can be used # if clamd is running in "LocalSocket" mode (*NOT* TCP/IP mode), and # socat is installed on the system (a check for socat is done). This # test can be enabled in the "User Edit" section below. # - Added a user configurable variable to attempt to restart clamd if # it's detected to not be running. # - Added notification when signature file updates are *NOT* detected and # databases are *NOT* reloaded, rather than just when they are detected. # - Added more portable secondary randomization code, removing the # requirement to have the bash shell installed. # - Added general improvements to the time randomization code so that # the time interval does not always end with a zero. # - Added user configurable min and max variables for setting time # randomization intervals (defaults to min=60 and max=600 seconds). # - Added terminal detection to determine whether the script is being # run manually or via cron. If run manually, the script will now # prompt the user to see if they want to delay the script execution # (random) or not. If "yes" is selected, then the script will pause # and display a visual countdown in seconds until script execution. # - Added a variable that the user must set before the script will run. # This will effectively require that script users at least minimally # review the "User Edit Section" before running the script. # - Rearranged some sections, timestame placement, and updated comments. # # Version 1.6 (updated 8/27/07) # - Added support for SecuriteInfo 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. export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" # Set ClamD user and group accounts. clam_user="clamav" clam_group="clamav" # Set path to ClamAV signature files location. If unsure, check # your clamd.conf file for the "DatabaseDirectory" path setting. clam_sigs="/var/lib/clamav" # Set path to clamd.pid file (see clamd.conf for path location). # To disable automatic signature database reloading, comment out # the next line (note, this does *NOT* restart clamd, it simply # signals clamd to reload its signature databases). clamd_pid="/var/run/clamav/clamd.pid" # If running clamd in "LocalSocket" mode (*NOT* in TCP/IP mode), and # either "SOcket Cat" (socat) or the "IO::Socket::UNIX" perl module # are installed on the system, and you want to report whether clamd # is running or not, uncomment the "clamd_socket" variable below (you # will be warned if neither socat nor IO::Socket::UNIX are found, but # the script will still run). You will also need to set the correct # path to your clamd socket file (if unsure of the path, check the # "LocalSocket" setting in your clamd.conf file for socket location). clamd_socket="/var/run/clamav/clamd.ctl" # If you would like to attemtp to restart ClamD if detected not running, # enter the clamd start command for your distro below and uncomment the # "start_clamd" line. The sample start command shown should work for most # linux distros. NOTE: this variable is dependant on the "clamd_socket" # variable above. If it's not enabled, then this variable will be ignored, # whether enabled or not. start_clamd="/etc/init.d/clamav-daemon start" # Set temporary working directory paths (edit to meet your own needs). If # these directories do not exist, the script will attempt to create them. tmp_dir="/var/tmp/clamdb" rsync_dir="/var/tmp/rsync" # Enable or disable download time randomization. This allows the script to # be executed via cron, but the actual signature file checking will pause # for a random number of seconds between the "min" and "max" time settings # specified below. This helps to more evenly distribute load on the host # download sites. To disable, set the following variable to "no". enable_random="yes" # If download time randomization is enabled above (enable_random="yes"), # then set the min and max radomization times intervals (in seconds). min_sleep_time="6" # Default minimum is 60 seconds (1 minute). max_sleep_time="20" # Default maximum is 600 seconds (10 minutes). # 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 # http://www.sanesecurity.com/clamav/junksigs/junk.ndb.gz # http://www.sanesecurity.com/clamav/roguesigs/rogue.hdb.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 " # SecuriteInfo source URLs - *MUST* be HTTP URLs, one URL per line. # Add/remove/modify URLs between quote makes as needed. To disable # SecuriteInfo downloads, comment out the next five lines. si_urls=" http://clamav.securiteinfo.com/vx.hdb.gz http://clamav.securiteinfo.com/honeynet.hdb.gz http://clamav.securiteinfo.com/securiteinfo.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_urls=" 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 # file downloads 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" # Default is 6 hours (4 downloads daily). # When running scripts via cron, output is often redirected to # /dev/null so that only error output is mailed to administrators. # However, curl reports stats to stderr whether successful or not. # If you want to silence the stats reported by curl, and only report # errors to stderr, change the following variable to "yes". curl_silence="yes" # Default is "no" to report all curl stats # Set the following variable to "yes" once you have completed the # configuration of the "USER EDIT SECTION" of this script above. user_configuration_complete="yes" ################################################################################ # END OF SCRIPT USER EDIT SECTION - YOU SHOULD NOT NEED TO EDIT ANYTHING BELOW # ################################################################################ # Check to see if the script's "USER EDIT SECTION" has been completed. if [ "$user_configuration_complete" = "no" -o -z "$user_configuration_complete" ] then echo "" echo " *** SCRIPT CONFIGURATION HAS NOT BEEN COMPLETED ***" echo " Please review and configure the 'USER EDIT SECTION' of the script." echo " Once the user configuration section is complete, rerun the script." echo "" exit 1 fi # 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 # Create a temporary "scan-test.txt" file for signature file testing. echo "Temporary clamscan test file..." > $tmp_dir/scan-test.txt # Change shell to the ClamAV signature files directory. cd $clam_sigs # Silence curl output and only report errors - useful if script is run via cron. if [ "$curl_silence" = "yes" ] then echo "" echo "The $0 setting will only report errors for curl downloads." curl_output_level="--silent --show-error" fi # If ClamD status check is enabled ("clamd_socket" variable is uncommented # and the socket path is correctly specified in "User Edit" section above), # then test to see if clamd is running or not. if [ -n "$clamd_socket" ] then socat="`which socat 2> /dev/null`" if [ -n "$socat" -a -x "$socat" ] then socket_cat1=1 if [ "`echo PING | socat - "$clamd_socket"`" = "PONG" ] then socket_cat2=1 echo "====================" echo "= ClamD is running =" echo "====================" fi else if [ "`perl -e 'use IO::Socket::UNIX; print $IO::Socket::UNIX::VERSION,"\n"' 2> /dev/null`" ] then io_socket1=1 if [ "`perl -MIO::Socket::UNIX -we '$s = IO::Socket::UNIX->new(shift); $s->print("PING"); \ print $s->getline; $s->close' "$clamd_socket" 2> /dev/null`" = "PONG" ] then io_socket2=1 echo "====================" echo "= ClamD is running =" echo "====================" fi fi fi if [ -z "$socket_cat1" -a -z "$io_socket1" ] then echo "" echo " --- WARNING ---" echo " It appears that neither 'SOcket CAT' (socat) nor the perl module" echo " 'IO::Socket::UNIX' are installed on the system. In order to run" echo " the ClamD socket test to determine whether ClamD is running or" echo " or not, either 'socat' or 'IO::Socket::UNIX' must be installed." echo "" echo " You can silence this warning by either installing 'socat' or the" echo " 'IO::Socket::UNIX' perl module, or by simply commenting out the" echo " 'clamd_socket' variable in the 'USER EDIT SECTION' of the script." else if [ -z "$socket_cat2" -a -z "$io_socket2" ] then echo "" echo " *************************" echo " * !!! ALERT !!! *" echo " * CLAMD IS NOT RUNNING! *" echo " *************************" echo "" if [ -n "$start_clamd" ] then echo " Attempting to start ClamD..." echo "" if [ -n "$socket_cat1" ] then [ "`$start_clamd 2> /dev/null`" -a "`sleep 5`" ] if [ "`echo PING | socat - "$clamd_socket" 2> /dev/null`" = "PONG" ] then echo "====================================" echo "= ClamD was successfully restarted =" echo "====================================" else echo " *************************" echo " * !!! PANIC !!! *" echo " * CLAMD FAILED TO START *" echo " *************************" echo "" echo "Check to confirm that the clamd start process defined for" echo "the 'start_clamd' variable in the 'USER EDIT SECTION' is" echo "set correctly for your particular distro. If it is, then" echo "check your logs to determine why clamd failed to start." echo "" exit 1 fi else if [ -n "$io_socket1" ] then [ "`$start_clamd 2> /dev/null`" -a "`sleep 5`" ] if [ "`perl -MIO::Socket::UNIX -we '$s = IO::Socket::UNIX->new(shift); \ $s->print("PING"); print $s->getline; $s->close' "$clamd_socket" \ 2> /dev/null`" = "PONG" ] then echo "====================================" echo "= ClamD was successfully restarted =" echo "====================================" else echo " *************************" echo " * !!! PANIC !!! *" echo " * CLAMD FAILED TO START *" echo " *************************" echo "" echo "Check to confirm that the clamd start process defined for" echo "the 'start_clamd' variable in the 'USER EDIT SECTION' is" echo "set correctly for your particular distro. If it is, then" echo "check your logs to determine why clamd failed to start." echo "" exit 1 fi fi fi fi fi fi fi # Signature update check, time randomization section. This script now # provides support for both bash and non-bash enabled system shells. if [ "$enable_random" = "yes" ] ; then if [ -n "$RANDOM" 2> /dev/null ] then sleep_time=$(($RANDOM * $(($max_sleep_time - $min_sleep_time)) / 32767 + $min_sleep_time)) else sleep_time=0 while [ "$sleep_time" -lt "$min_sleep_time" -o "$sleep_time" -gt "$max_sleep_time" ] ; do sleep_time=`head -1 /dev/urandom | cksum | awk '{print $2}'` done fi if [ ! -t 0 ] then echo "" echo "`date` - Pausing signature file updates for $sleep_time seconds..." sleep $sleep_time echo "" echo "`date` - Pause complete, checking for new signature files..." else echo "" echo -n "Running script manually, do you want to pause execution (y/n)?: " read response while [ "$response" != "y" -a "$response" != "n" ] ; do echo -n "Expecting either 'y' or 'n', do you want to pause script execution (y/n)?: " read response done if [ "$response" = "y" ] then seconds=$sleep_time echo "Starting unofficial ClamAV signature updates on `date`" echo "" while [ "$sleep_time" -ne 0 ] ; do echo -ne "Pausing signature updates for $seconds seconds. Time remaining: $sleep_time \r" sleep 1 sleep_time=$(($sleep_time - 1)) done echo "" echo "Pause complete, `date`, checking for new signature files..." else echo "Running unofficial ClamAV signature updates..." fi fi 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_urls ; do if [ `date +%s` -gt 0 2> /dev/null ] then current_time=`date +%s` else if [ `perl -le print+time 2> /dev/null` ] then current_time=`perl -le print+time` fi fi if [ "$current_time" -gt 0 2> /dev/null ] then echo "" echo "======================================================================" echo "Malware Black List $mbl_file Signature File Update" echo "======================================================================" echo "" if [ ! -s "$mbl_file" ] then curl $curl_output_level --connect-timeout 15 --max-time 60 -R -o $tmp_dir/$mbl_file $source_url test -s $tmp_dir/$mbl_file && \ clamscan --quiet -d $tmp_dir/$mbl_file $tmp_dir/scan-test.txt && \ mv -f $tmp_dir/$mbl_file . && \ do_clamd_reload=1 echo $current_time > $clam_sigs/last-mbl-update.txt echo "" fi if [ ! -s "$clam_sigs"/last-mbl-update.txt ] then echo $current_time > $clam_sigs/last-mbl-update.txt update_interval=$(($mbl_update_hours * 3600)) lastupdate_time=`cat $clam_sigs/last-mbl-update.txt` time_interval=$(($current_time - $lastupdate_time)) else update_interval=$(($mbl_update_hours * 3600)) lastupdate_time=`cat $clam_sigs/last-mbl-update.txt` time_interval=$(($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 $(($update_interval - 600)) ] then curl $curl_output_level --connect-timeout 15 --max-time 60 -R -o $tmp_dir/$mbl_file $source_url test -s $tmp_dir/$mbl_file && \ clamscan --quiet -d $tmp_dir/$mbl_file $tmp_dir/scan-test.txt && \ cp -f $mbl_file $mbl_file-bak && \ mv -f $tmp_dir/$mbl_file . && \ do_clamd_reload=1 echo $current_time > $clam_sigs/last-mbl-update.txt else time_remaining=$(($update_interval - $time_interval)) hours_left=$(($time_remaining / 3600)) minutes_left=$(($time_remaining % 3600 / 60)) echo "$mbl_update_hours hours have not yet elapsed since the last MBL update." echo "" echo " --- No update was performed at this time ---" echo "" echo "Next MBL update will be performed in approximately $hours_left hour(s), $minutes_left minute(s)" fi else echo "" echo " --- WARNING ---" echo "The system's date function does not appear to support 'date +%s', nor was" echo "'perl' located on the system. The MBL update was bypassed at this time." echo "" echo "You may silence this warning by either commenting out the 'mbl_urls' variable" echo "in the 'USER EDIT' section of the script, or by installing perl or the GNU" echo "date utility, either of which can calculate the needed seconds since epoch." 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 $curl_output_level --connect-timeout 15 --max-time 60 -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 $tmp_dir/scan-test.txt && \ # mv -f $tmp_dir/$target_file $tmp_dir/$source_file . && \ # do_clamd_reload=1 # else # curl $curl_output_level --connect-timeout 15 --max-time 60 -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 $tmp_dir/scan-test.txt && \ # 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 --timeout=30 -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 $tmp_dir/scan-test.txt && \ mv -f $tmp_dir/$target_file . && \ do_clamd_reload=1 else rsync --timeout=30 -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 $tmp_dir/scan-test.txt && \ cp -f $target_file $target_file-bak && \ mv -f $tmp_dir/$target_file . && \ do_clamd_reload=1 fi done # Check for an existing SecuriteInfo VX signature file. If it exists, then # run the update check. Otherwise, just download, extract and test the file. for source_url in $si_urls ; do source_file=`basename $source_url` target_file=`basename $source_url .gz` echo "" echo "======================================================================" echo "SecuriteInfo $target_file Signature File Update" echo "======================================================================" echo "" if [ ! -s "$target_file" ] then curl $curl_output_level --connect-timeout 15 --max-time 60 -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 $tmp_dir/scan-test.txt && \ mv -f $tmp_dir/$target_file $tmp_dir/$source_file . && \ do_clamd_reload=1 else curl $curl_output_level --connect-timeout 15 --max-time 60 -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 $tmp_dir/scan-test.txt && \ 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` else if [ -n "$clamd_pid" -a -z "$do_clamd_reload" ] ; then echo "" echo "=========================================================" echo "= No update(s) detected, NOT reloading ClamAV databases =" echo "=========================================================" fi fi exit $?