fetch-sanesecurity-sigs/fetch-sanesecurity-sigs -rwxr-xr-x 8.2 KiB View raw Log this file
9a8f5e40111d — Malcolm Scott Update comments post-hg-to-svn-conversion 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#!/bin/bash
#
# fetch-sanesecurity-sigs
# by Malcolm Scott
# <malcolm at retrosnub dot co dot uk>
#
# https://bitbucket.org/mas90/fetch-sanesecurity-sigs
#
# -----------------------------------------------------------------------------
# Copyright (C) 2009-2017 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.)
#


### Configuration ###

# ClamAV database location
clamd_dbdir="/var/lib/clamav"

# ClamAV daemon process ID file
# (If this is commented out, the daemon will not be reloaded automatically)
clamd_pidfile="/var/run/clamav/clamd.pid"

# Directory in which this script will keep its persistent data
data_dir="/var/lib/sanesecurity"

# Directory in which this script will keep its cache
# (This should not be the same as data_dir.  Any unexpected files in this
# directory will be deleted!)
cache_dir="/var/cache/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"

# Signatures we don't want, as a space-separated list
# (If this is empty we will load all signatures available on the mirror.
# See http://www.sanesecurity.co.uk/databases.htm for guidance on which
# signatures to choose.)
exclude="INetMsg-SpamDomains-2m.ndb winnow_phish_complete.ndb winnow_phish_complete_url.ndb MiscreantPunch099-INFO-Low.ldb"

# Extra options for rsync
# The default, --contimeout=30, makes for faster recovery if a mirror is
# blocking your connection (e.g. if you connect too frequently).  However
# this is not available in older versions of rsync so you may need to
# remove it.
# Additionally, if you have a slow link you may want to add -z here to
# enable compression.
rsync_extra_opts="--contimeout=30"

# Minimum interval between updates, in minutes
# (Note that the download servers may be configured to drop connections made
# at too great a rate)
min_interval="30"

# 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 GnuPG public key
gpg_key_url="http://www.sanesecurity.net/publickey.gpg"

# Location of GnuPG home directory
# (If you change this, be sure that you understand the security implications:
# signatures by *any* key in your public keyring will be accepted)
gpg_homedir="$data_dir/gnupg"

# Extra options for GnuPG, if required
gpg_extra_opts=""

# Exclude logical signatures (*.ldb)?
# These are not supported by versions of ClamAV prior to 0.94.
# If you use an old version of ClamAV, you should enable this option.
#exclude_ldb=1

### End of configuration ###


umask 0022

# 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 GnuPG, if necessary
if [ ! -d "$gpg_homedir" ]
then
	echo "GnuPG homedir is nonexistant; initialising" >&2
	echo "(This should only occur once)" >&2
	mkdir -p "$gpg_homedir"
	chmod 0700 "$gpg_homedir"
	gpg_tmp="$(mktemp -t fetch-sanesecurity-sigs.XXXXXXXXXX)"
	if ! wget -O "$gpg_tmp" "$gpg_key_url"
	then
		echo "ERROR: could not fetch GnuPG public key; aborting" >&2
		rm -f "$gpg_tmp"
		exit 4
	fi
	if ! gpg --homedir "$gpg_homedir" $gpg_extra_opts --import "$gpg_tmp"
	then
		echo "ERROR: could not import GnuPG public key; aborting" >&2
		rm -f "$gpg_tmp"
		exit 4
	fi
	rm -f "$gpg_tmp"
fi

# This appears to be the most portable way to find the current timestamp
# (suggestions on how to avoid calling perl are very welcome)
time_now="$(perl -le print+time)"
if [ ! "$time_now" -gt 1 ]
then
	echo "Could not find current timestamp -- is perl installed?" >&2
	exit 5
fi

# Check that min_interval seconds have elapsed since last run
if [ -s "$data_dir/update-stamp" ]
then
	time_then="$(cat "$data_dir/update-stamp")"
	minutes_elapsed=$(( (time_now - time_then) / 60 ))
	if [ "$minutes_elapsed" -lt "$min_interval" ]
	then
		echo "Must wait at least $min_interval minutes between updates; aborting" >&2
		exit 2
	fi
fi

# 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 [ "$exclude_ldb" = "1" ]
then
	exclude="$exclude *.ldb"
fi
if [ "$exclude" ]
then
	for i in $exclude
	do
		rsync_extra_opts="$rsync_extra_opts --exclude=$i --exclude=$i.*"
		rm -vf "$cache_dir"/$i "$cache_dir"/$i.*
	done
fi
if ! rsync --progress --delete -rt $rsync_extra_opts "$mirror/." "$cache_dir/"
then
	echo "rsync failed; aborting." >&2
	exit 3
fi
echo "$time_now" > "$data_dir/update-stamp"
chmod 0644 "$cache_dir"/*
echo

# Iterate through the databases in the cache
installed=0
for db in "$cache_dir"/*.?db "$cache_dir"/*.ftm
do
	db_name=$(basename "$db")
	db_live="$clamd_dbdir/sanesecurity-$db_name"

	# Only pay any attention to this database if it's newer than the installed version
	if [ -e "$db_live" -a ! "$db" -nt "$db_live" ]
	then
		echo "$db_name is already up-to-date; skipping"
		continue
	fi

	# Zero-length databases have no value and confuse the test below
	if [ ! -s "$db" ]
	then
		echo "$db_name is zero-length; discarding"
		continue
	fi

	# Check that the GnuPG signature is present and correct
	if ! gpg_out=$(gpg --homedir "$gpg_homedir" $gpg_extra_opts --verify "$db.sig" "$db" 2>&1)
	then
		echo "SECURITY ERROR: $db_name has a bad GnuPG signature; discarding:" >&2
		echo "$gpg_out" >&2
		continue
	fi

	# Test the database by asking ClamAV to check something with it
	if ! clamscan --quiet --tempdir="${TMPDIR:-/tmp}" --database="$db" - < /dev/null
	then
		echo "ERROR: $db_name fails a simple test; discarding" >&2
		continue
	fi

	# Now we can actually install this database
	echo "Installing $db_name into $db_live"
	if rsync -p "$db" "$db_live"
	then
		installed=$((installed+1))

		# Clean up stuff left behind by old scripts
		rm -vf "$clamd_dbdir/$db_name"*
	fi
done

# Clean up any databases which are now excluded but weren't previously
if [ "$exclude" ]
then
	for i in $exclude
	do
		db_live="$clamd_dbdir/sanesecurity-$i"
		if [ -f "$db_live" ]
		then
			rm -vf "$db_live"*
			installed=$((installed+1))
		fi
	done
fi

# 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 [ "$clamd_pidfile" -a -f "$clamd_pidfile" ]
	then
		echo "Reloading ClamAV daemon"
		clamdscan --reload
	fi
else
	echo "No databases installed."
fi

exit 0