source: trunk/fetch-sanesecurity-sigs

Last change on this file was 376, checked in by malcolm, 6 months ago

Exclude new risky databases

  • Property svn:executable set to *
  • Property svn:keywords set to Date Revision
File size: 8.5 KB
Line 
1#!/bin/bash
2#
3# fetch-sanesecurity-sigs
4# by Malcolm Scott, Retrosnub Internet Services
5# <malcolm at retrosnub dot co dot uk>
6#
7# http://www.retrosnub.co.uk/sanesecurity
8# svn://svn.sanesecurity.retrosnub.co.uk/
9#
10# $Revision: 376 $
11# $Date: 2017-01-26 13:26:38 +0000 (Thu, 26 Jan 2017) $
12#
13# -----------------------------------------------------------------------------
14# Copyright (C) 2009-2011 Malcolm Scott
15#
16# This program is free software; you can redistribute it and/or modify it under
17# the terms of the GNU General Public License version 2 as published by the
18# Free Software Foundation.
19#
20# This program is distributed in the hope that it will be useful, but WITHOUT
21# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
23#
24# You should have received a copy of the GNU General Public License along with
25# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26# Place, Suite 330, Boston, MA 02111-1307 USA
27# -----------------------------------------------------------------------------
28#
29# INSTALLATION AND USAGE:
30#
31#  * Ensure that you have wget, gpg and rsync installed (in addition to a
32#    standard set of UNIX tools).
33#  * Configure this script by editing the configuration variables below.
34#  * Set up cron to run this script periodically, at a randomly-selected time
35#    (i.e. not just on the hour unless unavoidable), not more often than once
36#    per hour.  The script should be run either as root or as the user clamd
37#    runs as.  For example, add the following line to /etc/crontab or a file
38#    in /etc/cron.d:
39#         42 * * * *  root  /path/to/fetch-sanesecurity-sigs >/dev/null
40#    (Redirection of the output to /dev/null is recommended when running from
41#    cron as the script is verbose in normal operation.  This will not hide
42#    errors, however.)
43#
44# Note that this script is tailored to the Sanesecurity setup (as of January
45# 2009).  It should replace scripts using the pre-2009 setup (HTTP).  It is
46# not intended to download non-Sanesecurity signatures; use another script
47# for that purpose.
48
49
50### Configuration ###
51
52# ClamAV database location
53clamd_dbdir="/var/lib/clamav"
54
55# ClamAV daemon process ID file
56# (If this is commented out, the daemon will not be reloaded automatically)
57clamd_pidfile="/var/run/clamav/clamd.pid"
58
59# Directory in which this script will keep its persistent data
60data_dir="/var/lib/sanesecurity"
61
62# Directory in which this script will keep its cache
63# (This should not be the same as data_dir.  Any unexpected files in this
64# directory will be deleted!)
65cache_dir="/var/cache/sanesecurity"
66
67# Mirror to use, in a form accepted by rsync
68# (Leave set to the round robin address unless you know what you are doing:
69# forcing the use of one particular mirror will cause excess load for that
70# mirror)
71mirror="rsync://rsync.sanesecurity.net/sanesecurity"
72
73# Signatures we don't want, as a space-separated list
74# (If this is empty we will load all signatures available on the mirror.
75# See http://www.sanesecurity.co.uk/databases.htm for guidance on which
76# signatures to choose.)
77exclude="INetMsg-SpamDomains-2m.ndb winnow_phish_complete.ndb winnow_phish_complete_url.ndb MiscreantPunch099-INFO-Low.ldb"
78
79# Extra options for rsync
80# The default, --contimeout=30, makes for faster recovery if a mirror is
81# blocking your connection (e.g. if you connect too frequently).  However
82# this is not available in older versions of rsync so you may need to
83# remove it.
84# Additionally, if you have a slow link you may want to add -z here to
85# enable compression.
86rsync_extra_opts="--contimeout=30"
87
88# Minimum interval between updates, in minutes
89# (Note that the download servers may be configured to drop connections made
90# at too great a rate)
91min_interval="30"
92
93# Randomly sleep before downloading if running noninteractively?
94# (Please leave this enabled, as it reduces peak load on the mirrors)
95random_sleep=1
96
97# URL of the Sanesecurity GnuPG public key
98gpg_key_url="http://www.sanesecurity.net/publickey.gpg"
99
100# Location of GnuPG home directory
101# (If you change this, be sure that you understand the security implications:
102# signatures by *any* key in your public keyring will be accepted)
103gpg_homedir="$data_dir/gnupg"
104
105# Extra options for GnuPG, if required
106gpg_extra_opts=""
107
108# Exclude logical signatures (*.ldb)?
109# These are not supported by versions of ClamAV prior to 0.94.
110# If you use an old version of ClamAV, you should enable this option.
111#exclude_ldb=1
112
113### End of configuration ###
114
115
116umask 0022
117
118# Check the configuration looks sane
119if [ ! -d "$clamd_dbdir" ]
120then
121        echo "clamd_dbdir ($clamd_dbdir) does not exist; aborting" >&2
122        echo "(check your configuration)" >&2
123        exit 1
124fi
125
126mkdir -p "$data_dir" "$cache_dir"
127
128# Set up GnuPG, if necessary
129if [ ! -d "$gpg_homedir" ]
130then
131        echo "GnuPG homedir is nonexistant; initialising" >&2
132        echo "(This should only occur once)" >&2
133        mkdir -p "$gpg_homedir"
134        chmod 0700 "$gpg_homedir"
135        gpg_tmp="$(mktemp -t fetch-sanesecurity-sigs.XXXXXXXXXX)"
136        if ! wget -O "$gpg_tmp" "$gpg_key_url"
137        then
138                echo "ERROR: could not fetch GnuPG public key; aborting" >&2
139                rm -f "$gpg_tmp"
140                exit 4
141        fi
142        if ! gpg --homedir "$gpg_homedir" $gpg_extra_opts --import "$gpg_tmp"
143        then
144                echo "ERROR: could not import GnuPG public key; aborting" >&2
145                rm -f "$gpg_tmp"
146                exit 4
147        fi
148        rm -f "$gpg_tmp"
149fi
150
151# This appears to be the most portable way to find the current timestamp
152# (suggestions on how to avoid calling perl are very welcome)
153time_now="$(perl -le print+time)"
154if [ ! "$time_now" -gt 1 ]
155then
156        echo "Could not find current timestamp -- is perl installed?" >&2
157        exit 5
158fi
159
160# Check that min_interval seconds have elapsed since last run
161if [ -s "$data_dir/update-stamp" ]
162then
163        time_then="$(cat "$data_dir/update-stamp")"
164        minutes_elapsed=$(( (time_now - time_then) / 60 ))
165        if [ "$minutes_elapsed" -lt "$min_interval" ]
166        then
167                echo "Must wait at least $min_interval minutes between updates; aborting" >&2
168                exit 2
169        fi
170fi
171
172# Random sleep (see comment in configuration section)
173if [ "$random_sleep" = "1" ]
174then
175        # Are we running noninteractively, i.e. without a tty on stdin?
176        if ! tty -s
177        then
178                # $RANDOM is between 0 and 32767.
179                # Use this to generate a time between 30 and 32767/200+30 = 193 seconds.
180                sleep_time=$((RANDOM/200+30))
181                echo "Sleeping for $sleep_time seconds."
182                sleep $sleep_time
183        fi
184fi
185
186# Update the cache
187if [ "$exclude_ldb" = "1" ]
188then
189        exclude="$exclude *.ldb"
190fi
191if [ "$exclude" ]
192then
193        for i in $exclude
194        do
195                rsync_extra_opts="$rsync_extra_opts --exclude=$i --exclude=$i.*"
196                rm -vf "$cache_dir"/$i "$cache_dir"/$i.*
197        done
198fi
199if ! rsync --progress --delete -rt $rsync_extra_opts "$mirror/." "$cache_dir/"
200then
201        echo "rsync failed; aborting." >&2
202        exit 3
203fi
204echo "$time_now" > "$data_dir/update-stamp"
205chmod 0644 "$cache_dir"/*
206echo
207
208# Iterate through the databases in the cache
209installed=0
210for db in "$cache_dir"/*.?db "$cache_dir"/*.ftm
211do
212        db_name=$(basename "$db")
213        db_live="$clamd_dbdir/sanesecurity-$db_name"
214
215        # Only pay any attention to this database if it's newer than the installed version
216        if [ -e "$db_live" -a ! "$db" -nt "$db_live" ]
217        then
218                echo "$db_name is already up-to-date; skipping"
219                continue
220        fi
221
222        # Zero-length databases have no value and confuse the test below
223        if [ ! -s "$db" ]
224        then
225                echo "$db_name is zero-length; discarding"
226                continue
227        fi
228
229        # Check that the GnuPG signature is present and correct
230        if ! gpg_out=$(gpg --homedir "$gpg_homedir" $gpg_extra_opts --verify "$db.sig" "$db" 2>&1)
231        then
232                echo "SECURITY ERROR: $db_name has a bad GnuPG signature; discarding:" >&2
233                echo "$gpg_out" >&2
234                continue
235        fi
236
237        # Test the database by asking ClamAV to check something with it
238        if ! clamscan --quiet --tempdir="${TMPDIR:-/tmp}" --database="$db" - < /dev/null
239        then
240                echo "ERROR: $db_name fails a simple test; discarding" >&2
241                continue
242        fi
243
244        # Now we can actually install this database
245        echo "Installing $db_name into $db_live"
246        if rsync -p "$db" "$db_live"
247        then
248                installed=$((installed+1))
249
250                # Clean up stuff left behind by old scripts
251                rm -vf "$clamd_dbdir/$db_name"*
252        fi
253done
254
255# Clean up any databases which are now excluded but weren't previously
256if [ "$exclude" ]
257then
258        for i in $exclude
259        do
260                db_live="$clamd_dbdir/sanesecurity-$i"
261                if [ -f "$db_live" ]
262                then
263                        rm -vf "$db_live"*
264                        installed=$((installed+1))
265                fi
266        done
267fi
268
269# Finished; display summary and perhaps reload clamd
270echo
271if [ "$installed" -gt 0 ]
272then
273        if [ "$installed" -eq 1 ]
274        then
275                s=""
276        else
277                s="s"
278        fi
279        echo "Installed $installed database$s"
280
281        # Is clamd running?
282        if [ "$clamd_pidfile" -a -f "$clamd_pidfile" ]
283        then
284                echo "Reloading ClamAV daemon"
285                clamdscan --reload
286        fi
287else
288        echo "No databases installed."
289fi
290
291exit 0
Note: See TracBrowser for help on using the repository browser.