@@ 0,0 1,208 @@
+#!/bin/bash
+#
+# fetch-sanesecurity-sigs
+# by Malcolm Scott, Retrosnub Internet Services
+# <malcolm at retrosnub dot co dot uk>
+#
+# $Revision$
+# $Date$
+#
+# -----------------------------------------------------------------------------
+# Copyright (C) 2009 Malcolm Scott
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License version 2 as published by the
+# Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+# -----------------------------------------------------------------------------
+#
+# INSTALLATION AND USAGE:
+#
+# * Ensure that you have wget, gpg and rsync installed (in addition to a
+# standard set of UNIX tools).
+# * Configure this script by editing the configuration variables below.
+# * Set up cron to run this script periodically, at a randomly-selected time
+# (i.e. not just on the hour unless unavoidable), not more often than once
+# per hour. The script should be run either as root or as the user clamd
+# runs as. For example, add the following line to /etc/crontab or a file
+# in /etc/cron.d:
+# 42 * * * * root /path/to/fetch-sanesecurity-sigs >/dev/null
+# (Redirection of the output to /dev/null is recommended when running from
+# cron as the script is verbose in normal operation. This will not hide
+# errors, however.)
+#
+# Note that this script is tailored to the Sanesecurity setup (as of January
+# 2009). It should replace scripts using the pre-2009 setup (HTTP). It is
+# not intended to download non-Sanesecurity signatures; use another script
+# for that purpose.
+
+
+### Configuration ###
+
+# ClamAV database location
+clamd_dbdir="/var/lib/clamav"
+
+# ClamAV daemon process ID file
+clamd_pidfile="/var/run/clamav/clamd.pid"
+
+# Directory in which this script will keep its cache
+cache_dir="/var/cache/sanesecurity"
+
+# Directory in which this script will keep its longer-term data
+data_dir="/var/lib/sanesecurity"
+
+# Mirror to use, in a form accepted by rsync
+# (Leave set to the round robin address unless you know what you are doing:
+# forcing the use of one particular mirror will cause excess load for that
+# mirror)
+mirror="rsync://rsync.sanesecurity.net/sanesecurity"
+
+# Extra options for rsync
+# For example, if you have a slow link you may want to add -z here to
+# enable compression.
+rsync_extra_opts=""
+
+# Minimum interval between updates, in a form accepted by 'touch -d'
+# (Note that the download servers may be configured to drop connections made
+# at too great a rate)
+min_interval="30 minutes"
+
+# Randomly sleep before downloading if running noninteractively?
+# (Please leave this enabled, as it reduces peak load on the mirrors.)
+random_sleep=1
+
+# URL of the Sanesecurity GPG public key
+gpg_key_url="http://www.sanesecurity.net/publickey.gpg"
+
+### End of configuration ###
+
+
+# Check the configuration looks sane
+if [ ! -d "$clamd_dbdir" ]
+then
+ echo "clamd_dbdir ($clamd_dbdir) does not exist; aborting" >&2
+ echo "(check your configuration)" >&2
+ exit 1
+fi
+
+mkdir -p "$data_dir" "$cache_dir"
+
+# Set up GPG, if necessary
+if [ ! -s "$data_dir/pubring.gpg" ]
+then
+ echo "No GPG keyring found; initialising" >&2
+ echo "(This should only occur once)" >&2
+ wget -O- "$gpg_key_url" | gpg --no-default-keyring --keyring "$data_dir/pubring.gpg" --import -
+fi
+
+# Check that min_interval seconds have elapsed since last run
+threshold_tmpfile="$(mktemp -t fetch-sanesecurity-sigs.XXXXXXXXXX)"
+touch -d "-$min_interval" "$threshold_tmpfile"
+if [ -e "$data_dir/update-stamp" -a "$data_dir/update-stamp" -nt "$threshold_tmpfile" ]
+then
+ rm "$threshold_tmpfile"
+ echo "Must wait at least $min_interval between updates; aborting" >&2
+ exit 2
+fi
+rm "$threshold_tmpfile"
+
+# Random sleep (see comment in configuration section)
+if [ "$random_sleep" = "1" ]
+then
+ # Are we running noninteractively, i.e. without a tty on stdin?
+ if ! tty -s
+ then
+ # $RANDOM is between 0 and 32767.
+ # Use this to generate a time between 30 and 32767/200+30 = 193 seconds.
+ sleep_time=$((RANDOM/200+30))
+ echo "Sleeping for $sleep_time seconds."
+ sleep $sleep_time
+ fi
+fi
+
+# Update the cache
+if ! rsync --progress --delete -rt $rsync_extra_opts "$mirror/." "$cache_dir/"
+then
+ echo "rsync failed; aborting." >&2
+ exit 3
+fi
+touch "$data_dir/update-stamp"
+echo
+
+# Iterate through the databases in the cache
+installed=0
+for db in "$cache_dir"/*.?db
+do
+ db_name=$(basename "$db")
+
+ # Only pay any attention to this database if it's newer than the installed version
+ if [ -e "$clamd_dbdir/sanesecurity-$db_name" -a ! "$db" -nt "$clamd_dbdir/sanesecurity-$db_name" ]
+ then
+ echo "$db_name is already up-to-date; skipping"
+ continue
+ fi
+
+ # Check that there actually is a GPG signature
+ # (there should be, and its absence could be due to tampering)
+ if [ ! -e "$db.sig" ]
+ then
+ echo "SECURITY ERROR: $db_name is missing a GPG signature; discarding" >&2
+ continue
+ fi
+
+ # Check that the GPG signature is correct
+ if ! gpg_out=$(gpg --no-default-keyring --keyring "$data_dir/pubring.gpg" --verify "$db.sig" "$db" 2>&1)
+ then
+ echo "SECURITY ERROR: $db_name has a bad GPG signature; discarding:" >&2
+ echo "$gpg_out" >&2
+ continue
+ fi
+
+ # Test the database by asking ClamAV to check something with it
+ if ! clamscan --quiet --database="$db" - < /dev/null
+ then
+ echo "ERROR: $db_name fails a simple test; discarding" >&2
+ continue
+ fi
+
+ # Now we can actually install this database
+ if cp -v "$db" "$clamd_dbdir/sanesecurity-$db_name"
+ then
+ installed=$(($installed + 1))
+
+ # Clean up stuff left behind by old scripts
+ rm -fv "$clamd_dbdir/$db_name"*
+ fi
+done
+
+# Finished; display summary and perhaps reload clamd
+echo
+if [ "$installed" -gt 0 ]
+then
+ if [ "$installed" -eq 1 ]
+ then
+ s=""
+ else
+ s="s"
+ fi
+ echo "Installed $installed database$s"
+
+ # Is clamd running?
+ if [ -f "$clamd_pidfile" ]
+ then
+ echo "Reloading ClamAV daemon"
+ kill -USR2 $(cat "$clamd_pidfile")
+ fi
+else
+ echo "No databases installed."
+fi
+
+exit 0
+