Initial version of fetch-sanesecurity-sigs
1 files changed, 208 insertions(+), 0 deletions(-)

A => fetch-sanesecurity-sigs
A => fetch-sanesecurity-sigs +208 -0
@@ 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
+