| May 21, 2014 | Updated MIMEDefang version | |
| Updated sendmail version | ||
| Other minor updates |
Send corrections, suggestions, and comments about this HOWTO to Mickey Hill <mickey@mickeyhill.com>. Please do not send installation or configuration questions to this address; instead, post them to the MIMEDefang mailing list.
MIMEDefang is a trademark of Roaring Penguin Software Inc.
CanIt is a trademark of Roaring Penguin Software Inc.
Linux is a registered trademark of Linus Torvalds.
UNIX is a registered trademark of The Open Group in the United States and other countries.
Fedora is a trademark or registered trademark of Red Hat, Inc.
Red Hat is a registered trademark of Red Hat, Inc.
Slackware is a registered trademark of Slackware Linux, Inc.
Yellow Dog is a trademark of Terra Soft Solutions of Colorado, Inc.
Solaris is a trademark or registered trademark of Sun Microsystems, Inc. in the United States and other countries.
BSD is a registered trademark of Berkeley Software Design, Inc.
AIX is a trademark or registered trademark of IBM Corporation.
IRIX is a trademark or registered trademark of Silicon Graphics, Inc. in the United States and other countries.
Sendmail is a registered trademark of Sendmail, Inc.
QPopper is a trademark of QUALCOMM Inc.
Network Associates and McAfee are registered trademarks of Network Associates, Inc.
AntiVir is a registered trademark of H+BEDV Datentechnik GmbH.
All other registered and unregistered trademarks in this document are the property of their respective owners.
MIMEDefang is an open-source product, and technical support is primarily provided through the MIMEDefang mailing list. For commercial support, please consider CanIt, a commercial product based on MIMEDefang and offered by Roaring Penguin Software.
A typical MIMEDefang installation consists of sendmail, MIMEDefang, SpamAssassin, and one or more open-source or commercial antivirus scanners.
MIMEDefang consists of four major components: mimedefang, mimedefang-multiplexor, mimedefang.pl, and mimedefang-filter. mimedefang is written in C, and is the actual mail filter that interfaces with sendmail. mimedefang splits incoming messages into parts and calls mimedefang-multiplexor to act on each message. mimedefang-multiplexor creates and manages a pool of Perl processes that execute mimedefang.pl, a Perl script. mimedefang.pl then operates on the message parts. mimedefang.pl does not normally need modification. mimedefang-filter is a Perl fragment that is read by mimedefang.pl, and serves as the configuration file. This configuration file is where the vast majority of user customization takes place.
More advanced configurations can entirely replace mimedefang.pl and mimedefang-filter with a custom filter that is executed by mimedefang.
MIMEDefang is licensed under the GNU General Public License.
In general, hardware requirements are the same as for sendmail. However, antivirus and spam detection software often require additional hardware resources (memory, cpu, and/or disk).
Perl 5.001 or greater is required by MIMEDefang. Some other packages described in this document may require a later version.
This HOWTO was written using Red Hat Linux 7.2, and updated using Fedora Core 5 Linux. Installation on other versions of Linux, on a BSD derivative, or on UNIX should be similar; however, directory and file names and locations may be different, and installation techniques may vary.
Correct timekeeping is essential to any mail server. NTP (network time protocol) and ntpd (the NTP daemon) are recommended for this purpose.
A permanent connection to the Internet is assumed. While a mail server with sendmail can be run using only a dial-up or other intermittent connection, such a configuration is beyond the scope of this document.
MIMEDefang should compile on any modern Linux, BSD derivative, or UNIX system. It has been known to compile on the following systems:
Fedora 9 Linux
Fedora 8 Linux
Fedora 7 Linux
Fedora Core 6 Linux
Fedora Core 5 Linux
Fedora Core 4 Linux
Fedora Core 3 Linux
Fedora Core 2 Linux
Fedora Core 1 Linux
Red Hat Linux 9
Red Hat Linux 8.0
Red Hat Linux 7.3
Red Hat Linux 7.2
Red Hat Linux 7.1
Red Hat Linux 7.0
Red Hat Linux 6.2
Red Hat Linux 6.1
Red Hat Enterprise Linux ES 4
Red Hat Enterprise Linux ES 2.1
CentOS 4.4
CentOS 4.0
SUSE Linux Enterprise Server 9
SUSE Linux 8.1
SUSE Linux 7.3
Slackware Linux 10.1
Slackware Linux 10.0
Slackware Linux 9.0
Slackware Linux 8.1
Slackware Linux 8.0
Slackware Linux 7.1
Slackware Linux 7.0
Gentoo 1.4
Yellow Dog Linux 3.0.1
Caldera Open Linux 3.1
Trustix 2.1
Trustix 2.0
Linux From Scratch 3.0
Ubuntu 2.6.15-51-server
Solaris 10
Solaris 9
Solaris 8
Solaris 7
Solaris 2.5.1
FreeBSD 5.2.1-RELEASE
FreeBSD 4.9-STABLE
FreeBSD 4.5-STABLE
OpenBSD 3.0
Mac OS X 10.4
AIX 5.3
AIX 5.2
AIX 5.1
AIX 4.3.3
HP-UX 11.00
Tru64 Unix 5.0A
IRIX 6.5.21
IRIX 6.5.20
If you have successfully compiled and installed MIMEDefang on a system not listed here, please send a brief email with your operating system name and exact version number to Mickey Hill <mickey@mickeyhill.com>.
MIMEDefang has been operated on single mail servers processing fewer than 100 messages per day to clusters of mail servers processing more than 4 million messages per day.
The more you think this doesn't apply to you, the more it does. :)
Sendmail version 8.12.0 or later is required by MIMEDefang. Version 8.14.9 or later is recommended. Earlier versions (8.11.x) contain errors in the libmilter code and may not work reliably. Versions prior to 8.14.9 contain known security vulnerabilities.
Although many people have success installing sendmail from vendor packages, it is this author's opinion that the least problematic and most repeatable, reliable results are obtained by installing sendmail from the original source from sendmail.org.
Download and unpack the source
Enable milter support in devtools/Site/site.config.m4
Build the source
Create cf/cf/sendmail.mc
Build and install the cf files
Create smmsp user and group.
Create symbolic link for man page directory.
Install
Build and install mailstats
Build and install makemap
Build and install libmilter
Build and install smrsh
Install headers and libraries for MIMEDefang
Edit /etc/mail/local-host-names
Edit /etc/mail/relay-domains
Edit /etc/mail/virtusertable
Edit /etc/mail/aliases
Create /etc/init.d/sendmail with queue runner and MIMEDefang support
Link startup script in rc3.d, rc0.d, and rc6.d
Create the /usr/src/sendmail directory and cd to it.
The latest source is available from ftp://ftp.sendmail.org/pub/sendmail/. This example uses version 8.14.9.
Download the source at ftp://ftp.sendmail.org/pub/sendmail/sendmail.8.14.9.tar.gz.
Unpack the source:
tar xvzf sendmail.8.14.9.tar.gz
Remove the source:
rm sendmail.8.14.9.tar.gz
Cd into the sendmail-8.14.9 directory.
Beginning with version 8.13.0, sendmail is compiled by default with support for the milter API. Also, libmilter will not unlink a socket when running as root, which was the recommended, but not default, configuration in previous versions.
In versions prior to 8.13.0, sendmail did not support mail filters by default, and must be compiled with filter support enabled by defining -DMILTER. To do this, create devtools/Site/site.config.m4 with the following lines:
dnl Milter APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER') APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER_ROOT_UNSAFE')
The first APPENDDEF enables the mail filter interface. The second APPENDDEF keeps libmilter from unlinking a socket when running as root. It is strongly recommended that MIMEDefang is not run as root. MIMEDefang does not need root access to communicate with sendmail.
To enable SMTP AUTH, devtools/Site/site.config.m4 should also contain these lines:
APPENDDEF(`conf_sendmail_ENVDEF', `-DSASL=2') APPENDDEF(`conf_sendmail_LIBS', `-lsasl2')
In the sendmail/ directory, build the source:
sh Build
NOTE: If this is not the first build in this directory tree, and you have changed or created any of the configuration files in the devtools/Site directory since the last build, use the -c option ("sh Build -c") to clear the previous build configuration. This may be the case if you forgot the site.config.m4 file the first time, or if your distribution preinstalled sendmail without milter support.
Change to the cf/cf/ directory. Copy generic-linux.mc to sendmail.mc. Next, tailor it as explained in cf/README.
Example sendmail.mc file:
divert(-1)dnl # # Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 # The Regents of the University of California. All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # divert(0)dnl VERSIONID(`$Id: generic-linux.mc,v 8.1 1999/09/24 22:48:05 gshapiro Exp $') OSTYPE(linux)dnl DOMAIN(generic)dnl define(`confBAD_RCPT_THROTTLE', `3')dnl define(`confTO_IDENT',`0s')dnl define(`confMILTER_LOG_LEVEL',`1')dnl define(`confAUTH_OPTIONS', `A')dnl FEATURE(`virtusertable',`hash -o /etc/mail/virtusertable')dnl FEATURE(`smrsh',`/usr/sbin/smrsh')dnl FEATURE(`always_add_domain')dnl FEATURE(`use_cw_file')dnl FEATURE(`local_procmail')dnl INPUT_MAIL_FILTER(`mimedefang', `S=unix:/var/spool/MIMEDefang/mimedefang.sock, F=T, T=S:1m;R:1m') MAILER(local)dnl MAILER(smtp)dnl MAILER(procmail)dnlThe important line is INPUT_MAIL_FILTER. This tells sendmail to send all mail through the specified filter.
The sendmail documentation includes this information about INPUT_MAIL_FILTER:
[Y]ou can override the default timeouts used by sendmail when
talking to the filters using the T= equate. There are four fields inside
of the T= equate:
Letter Meaning
C Timeout for connecting to a filter (if 0, use system timeout)
S Timeout for sending information from the MTA to a filter
R Timeout for reading reply from the filter
E Overall timeout between sending end-of-message to filter
and waiting for the final acknowledgment
Note the separator between each is a ';' as a ',' already separates equates
and therefore can't separate timeouts. The default values (if not set in
the config) are:
T=C:5m;S:10s;R:10s;E:5m
where 's' is seconds and 'm' is minutes.
NOTE: Some users of MIMEDefang and SpamAssassin have had troubles with filter
timeouts. This can be somewhat helped by increasing the timeouts:
INPUT_MAIL_FILTER(`mimedefang', `S=unix:/var/spool/MIMEDefang/mimedefang.sock, F=T, T=S:5m;R:5m')NOTE: This configuration is designed so that if the filter (MIMEDefang) fails for any reason while receiving an email, the mail server will return a tempfail code and "Please try again later" message. This is highly recommended if you are scanning for viruses, so that incoming messages are rejected if there is any error.
On the other hand, IF you are only scanning for spam and not for viruses, IF it is more important to you that you get the incoming message no matter what, and IF you are CERTAIN that there is no risk to you or your users if an email is accepted even if there is an error in the filter, you may wish to allow incoming messages to be accepted if the filter fails. To do this, remove the F=T flag.
INPUT_MAIL_FILTER(`mimedefang', `S=unix:/var/spool/MIMEDefang/mimedefang.sock, T=S:5m;R:5m')Build the cf file:
sh Build sendmail.cfIf this is not a new installation, back up your current /etc/mail/sendmail.cf and the sendmail binary in /usr/sbin.
If this is a new installation, create the /etc/mail directory if it does not exist:
mkdir /etc/mail
Install sendmail.cf as /etc/mail/sendmail.cf and submit.cf as /etc/mail/submit.cf:
sh Build install-cfCreate a new user smmsp and a new group smmsp with ID's of 25.
/usr/sbin/useradd -u 25 -d /var/spool/mqueue -r -s /sbin/nologin smmsp
Create a symbolic link for the man pages:
ln -s /usr/share/man /usr/manIn the sendmail/ directory, install the sendmail binary:
sh Build install cd ..
For each of the associated sendmail utilities (makemap, mailstats, etc.), read the README in the utility's directory. When you are ready to install it, back up your installed version and type "sh Build install". At a minimum, makemap and libmilter must be installed. If you use smrsh or other utilities, install them as well.
cd mailstats sh Build sh Build install cd .. cd makemap sh Build sh Build install cd .. cd libmilter sh Build sh Build install cd .. cd smrsh sh Build sh Build install cd ..Cd into the /usr/src/sendmail/sendmail-8.14.9 directory.
Install headers and libraries for MIMEDefang:
mkdir -p /usr/local/include/sendmail cp -R include/* /usr/local/include/sendmail/ cp -R sendmail/*.h /usr/local/include/sendmail/ mkdir -p /usr/local/lib cp obj.Linux.2.6.17-1.2174_FC5.i686/*/*.a /usr/local/lib/NOTE: On the last "cp" command, replace "obj.Linux.2.6.17-1.2174_FC5.i686" with the appropriate "obj.*" directory created by the sendmail build script.
/etc/mail/local-host-names should have the following lines:
# local-host-names - include all aliases for your machine here. yourcompany.com mail.yourcompany.comCreate /etc/mail/relay-domains with the following lines:
# relay-domains - Hosts for which relaying is permitted yourcompany.comEdit /etc/mail/virtusertable as desired.
Edit /etc/mail/aliases and change the alias for root to a valid address.
# Uncomment and *CHANGE* this! root: insert-human-being-hereCreate or edit startup/shutdown script at /etc/init.d/sendmail to start MIMEDefang. Be sure to chmod 755. The sample script below is the Fedora Core default script with these two lines added:
/etc/init.d/mimedefang start /etc/init.d/mimedefang stopOn other systems, add those two lines where appropriate to start MIMEDefang before the sendmail daemon starts, and stop MIMEDefang after the sendmail daemon stops.
The 'mimedefang' init script is included with MIMEDefang and must be manually installed into /etc/init.d (or other appropriate location) during MIMEDefang installation.
In addition, you must run a queue runner to periodically check for administrative messages generated by MIMEDefang. A queue runner is a separate sendmail process that retrieves and sends messages from a queue directory. The default Fedora Core script starts a queue runner automatically, although the default interval may be too long. On other systems, a queue runner can be started by adding the following line to your init script, after the main sendmail process is started:
sendmail -Ac -qp5mThe '5m' represents the interval at which the queue runner checks for mail (in this case, 5 minutes). This time can be changed to suit your personal preference. The Fedora Core sample script relies on /etc/sysconfig/sendmail, which should contain these lines. Note the change in queue runner time from the default 1h to 5m:
DAEMON=yes QUEUE=5mFedora Core sample init script:
#!/bin/bash
#
# sendmail This shell script takes care of starting and stopping
# sendmail.
#
# chkconfig: 2345 80 30
# description: Sendmail is a Mail Transport Agent, which is the program \
# that moves mail from one machine to another.
# processname: sendmail
# config: /etc/mail/sendmail.cf
# pidfile: /var/run/sendmail.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network
# Source sendmail configureation.
if [ -f /etc/sysconfig/sendmail ] ; then
. /etc/sysconfig/sendmail
else
DAEMON=no
QUEUE=1h
fi
[ -z "$SMQUEUE" ] && SMQUEUE="$QUEUE"
[ -z "$SMQUEUE" ] && SMQUEUE=1h
# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 0
[ -f /usr/sbin/sendmail ] || exit 0
RETVAL=0
prog="sendmail"
start() {
# Start daemons.
/etc/init.d/mimedefang start
echo -n $"Starting $prog: "
if test -x /usr/bin/make -a -f /etc/mail/Makefile ; then
make all -C /etc/mail -s > /dev/null
else
for i in virtusertable access domaintable mailertable ; do
if [ -f /etc/mail/$i ] ; then
makemap hash /etc/mail/$i < /etc/mail/$i
fi
done
fi
/usr/bin/newaliases > /dev/null 2>&1
daemon /usr/sbin/sendmail $([ "x$DAEMON" = xyes ] && echo -bd) \
$([ -n "$QUEUE" ] && echo -q$QUEUE) $SENDMAIL_OPTARG
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/sendmail
if ! test -f /var/run/sm-client.pid ; then
echo -n $"Starting sm-client: "
touch /var/run/sm-client.pid
chown smmsp:smmsp /var/run/sm-client.pid
if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
/sbin/restorecon /var/run/sm-client.pid
fi
daemon --check sm-client /usr/sbin/sendmail -L sm-msp-queue -Ac \
-q $SMQUEUE $SENDMAIL_OPTARG
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/sm-client
fi
return $RETVAL
}
reload() {
# Stop daemons.
echo -n $"reloading $prog: "
/usr/bin/newaliases > /dev/null 2>&1
if [ -x /usr/bin/make -a -f /etc/mail/Makefile ]; then
make all -C /etc/mail -s > /dev/null
else
for i in virtusertable access domaintable mailertable ; do
if [ -f /etc/mail/$i ] ; then
makemap hash /etc/mail/$i < /etc/mail/$i
fi
done
fi
daemon /usr/sbin/sendmail $([ "x$DAEMON" = xyes ] && echo -bd) \
$([ -n "$QUEUE" ] && echo -q$QUEUE)
RETVAL=$?
killproc sendmail -HUP
RETVAL=$?
echo
if [ $RETVAL -eq 0 -a -f /var/run/sm-client.pid ]; then
echo -n $"reloading sm-client: "
killproc sm-client -HUP
RETVAL=$?
echo
fi
return $RETVAL
}
stop() {
# Stop daemons.
echo -n $"Shutting down $prog: "
killproc sendmail
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sendmail
if test -f /var/run/sm-client.pid ; then
echo -n $"Shutting down sm-client: "
killproc sm-client
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/run/sm-client.pid
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sm-client
fi
/etc/init.d/mimedefang stop
return $RETVAL
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
RETVAL=$?
;;
restart)
stop
start
RETVAL=$?
;;
condrestart)
if [ -f /var/lock/subsys/sendmail ]; then
stop
start
RETVAL=$?
fi
;;
status)
status sendmail
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart|status}"
exit 1
esac
exit $RETVAL
Enable sendmail:
/sbin/chkconfig sendmail resetCreate the mqueue directory:
mkdir /var/spool/mqueue chmod 700 /var/spool/mqueue
Many mainstream distributions include some or all of these packages.
Qpopper provides POP3 services only.
NOTE: You do not need Qpopper if you are installing Cyrus IMAP or Dovecot. Each of these includes its own integrated POP3 server. If you want POP3 only, install Qpopper; for POP3, IMAP, and webmail, install Cyrus IMAP or Dovecot and SquirrelMail.
The Cyrus IMAP server provides both POP3 and IMAP services.
Dovecot provides both POP3 and IMAP services.
SquirrelMail is a web mail client that connects to an IMAP server. It is compatible with both Cyrus IMAP and Dovecot.
LANG="en_US"Several Perl modules are required for proper operation. For those who are familiar with the installation process, the required modules, along with the locations of the latest versions as of this writing, are:
IO-stringy
http://www.cpan.org/authors/id/D/DS/DSKOLL/IO-stringy-2.110.tar.gz
Search CPAN for latest distribution
MIME-Base64
http://www.cpan.org/authors/id/GAAS/MIME-Base64-3.07.tar.gz
Search CPAN for latest distribution
NOTE: Many Linux distributions include an old version of MIME::Base64 in the
core Perl distribution. In order to install a new version of MIME::Base64
without upsetting your Linux updating tools (like up2date or the equivalent),
you should specify INSTALLDIRS=site.
MailTools
http://www.cpan.org/authors/id/M/MA/MARKOV/MailTools-1.77.tar.gz
Search CPAN for latest distribution
MIME-tools
http://www.cpan.org/authors/id/D/DO/DONEILL/MIME-tools-5.427.tar.gz
Search CPAN for latest distribution
Digest-SHA1
http://www.cpan.org/authors/id/GAAS/Digest-SHA1-2.11.tar.gz
Search CPAN for latest distribution
libnet
http://www.cpan.org/authors/id/GBARR/libnet-1.22.tar.gz
Search CPAN for latest distribution
Mail-Audit
http://www.cpan.org/authors/id/R/RJ/RJBS/Mail-Audit-2.223.tar.gz
Search CPAN for latest distribution
Time-HiRes
http://www.cpan.org/authors/id/J/JH/JHI/Time-HiRes-1.9715.tar.gz
Search CPAN for latest distribution
HTML-Tagset
http://www.cpan.org/authors/id/P/PE/PETDANCE/HTML-Tagset-3.20.tar.gz
Search CPAN for latest distribution
HTML-Parser
http://www.cpan.org/authors/id/G/GA/GAAS/HTML-Parser-3.56.tar.gz
Search CPAN for latest distribution
Compress-Zlib
http://www.cpan.org/authors/id/P/PM/PMQS/Compress-Zlib-2.011.tar.gz
Search CPAN for latest distribution
Archive-Zip
http://www.cpan.org/authors/id/A/AD/ADAMK/Archive-Zip-1.23.tar.gz
Search CPAN for latest distribution
Perl modules can be installed in a number of ways. Generally, using packages provided by your distribution vendor is preferrable. When some or all are not available from your vendor, modules can be installed from CPAN manually, or installation can be automated using the CPAN module or by using cpan2rpm or other similar packaging tools. See Installing CPAN Modules for more information.
Cd to the /tmp directory.
The latest source is available from http://spamassassin.apache.org/downloads.cgi. This example uses version 3.3.1.
Download the SpamAssassin source at http://www.apache.org/dist/spamassassin/source/Mail-SpamAssassin-3.3.1.tar.gz.
Unpack the source:
tar xvzf Mail-SpamAssassin-3.3.1.tar.gzRemove the source:
rm Mail-SpamAssassin-3.3.1.tar.gzCd into the Mail-SpamAssassin-3.3.1 directory.
Install the source:
perl Makefile.PL make su -c 'make install'NOTE: Don't "make test" - it does a lot of unnecessary tests we don't need, and can potentially start so many processes that a running sendmail process will reject new connections because of high server utilization.
To disable Bayesian filtering, change the following in /etc/mail/spamassassin/local.cf:
use_bayes 0Download rules:
sa-updateAdd sa-update to root's crontab to keep rules updated daily.
Test:
spamassassin -t < sample-nonspam.txt > nonspam.out spamassassin -t < sample-spam.txt > spam.outVerify (using a text viewer, ie. "less") that nonspam.out has not been tagged as spam, and that spam.out has.
Cd to the /tmp directory.
Remove the source directory:
rm -rf Mail-SpamAssassin-3.3.1
AvpLinux
Bitdefender
clamav
Command Anti-Virus
File::Scan
FRISK F-Prot
F-Secure Anti-Virus
H+BEDV Antivir
Kaspersky
NAI McAfee uvscan
Norman Virus Control
OpenAntiVirus
Sophie
Sophos Sweep
Symantec CarrierScan
Trend Micro vscan
Trophie
Vexira
MIMEDefang automatically detects these virus scanners if they are installed in their default locations.
cd /tmp mkdir vlp4510l cd vlp4510l
Copy the source package into the temporary directory.
Unpack the source:
tar xvzf vlp4510l.tar.ZRemove the source:
rm vlp4510l.tar.ZInstall the source:
./install-uvscanThe install script asks a series of questions. Accept the defaults unless you know you need a non-standard installation.
Cd to the /tmp directory.
Remove the source directory:
rm -rf vlnx414lCheck the installation:
uvscan --versionIf you get this error, you need the compatibility libraries. Download and install the compat-libstdc++-33 rpm for Fedora Core Linux.
uvscan: error while loading shared libraries: libstdc++.so.5: cannot open shared object file: No such file or directoryTo update virus definitions automatically, install the following update script. Be sure to change the email addresses and SMTP server name. Install as /usr/local/uvscan/update and add to root's crontab:
0 */6 * * * /usr/local/uvscan/updateSample update script:
#!/usr/bin/perl -w
# uvscan virus DAT file updater written by
# Michael Matsumura (michael+uvscan@limit.org)
# Version 1.0
#
# Slightly modified by Mickey Hill
#
# Net::FTP and MIME::Lite are required for operation
# and 'tar' should be in the PATH
#
use strict;
use Net::FTP;
use MIME::Lite;
#
# Set to the directory uvscan is located/installed in
#
my $uvscan_directory = "/usr/local/uvscan";
#
# Set to the temporary directory to download the dat archive
#
my $tempdir = "/tmp/dat-updates";
#
# Set to email address for anonymous FTP login
#
my $emailaddress = 'postmaster@mycompany.com';
my $mailto = 'me@mycompany.com';
my $smtpserver = 'mail.mycompany.com';
# Define global variables
#
my ($ftp, @dirlist, $arraywalk, $localver, $serverver, $localfile,
@files, $file, $report, $notify);
$report = "Mail server virus definition update\n" . localtime() . "\n\n";
# Get the local uvscan datfile version
#
$localver = &checkuvscanver;
print "Currently installed version: ".$localver."\n";
$report .= "Currently installed version: ".$localver."\n";
# Create FTP connection
#
$ftp = Net::FTP->new("ftp.nai.com", Debug => 0);
# Login
#
$ftp->login("anonymous",$emailaddress);
$ftp->cwd("/pub/antivirus/datfiles/4.x");
$ftp->binary();
@dirlist = $ftp->ls();
foreach $arraywalk (@dirlist) {
if ($arraywalk =~ /dat-([0-9]+)\.tar/i) {
$serverver = $1;
print "Version on ftp.nai.com: ".$serverver."\n";
$report .= "Version on ftp.nai.com: ".$serverver."\n";
if ($serverver > $localver) {
$notify++;
print "Updating virus data files...\n";
$report .= "Updating virus data files...\n";
# Create and then change the working dir to $tempdir
#
if (!(-d $tempdir)) {
mkdir($tempdir, 700) or die("ERROR: Couldn't make temporary directory: $tempdir");
}
chdir $tempdir or die("ERROR: Couldn't change directory to tempdir:
$tempdir");
# Download the dat file!
#
$localfile = $ftp->get($arraywalk);
print "Download complete...updating now\n";
$report .= "Download complete...updating now\n";
# Untar the files, store the names of them into an array
#
@files = `tar -xvf $arraywalk`;
foreach $file (@files) {
# A line break is at the end of each $file...chomp that off
#
chomp($file);
# Move each file to the uvscan_directory; and make sure they
# are lowercase
#
my $movestring = "mv $file ".$uvscan_directory."/".lc($file);
print " ".$movestring."\n";
$report .= " ".$movestring."\n";
system($movestring);
}
# Make sure that the installation worked, by checking if
# the virus scanner reports the same data file version as
# the one we downloaded.
#
if (&checkuvscanver eq $serverver) {
print "Installation successful\n";
$report .= "Installation successful\n";
} else {
print "Error in installation, please install manually\n";
$report .= "Error in installation, please install manually\n";
}
#
# Cleanup...
#
print "Cleaning up\n";
$report .= "Cleaning up\n";
# Remove downloaded dat archive
#
unlink($arraywalk) or die("ERROR: Couldn't delete dat file: $arraywalk");
# Change to filesys root and remove temporary directory
#
chdir("/");
rmdir($tempdir) or die("ERROR: Couldn't remove tempdir: $tempdir");
} else { # if ($serverver > $localver) {
print "DAT files are the same... no need to update\n";
}
# Don't want to continue if there is more than one 'dat-[0-9]+.tar' files
#
last;
}
}
$ftp->quit;
if ($notify) {
my $msg = MIME::Lite->new(
From =>$emailaddress,
To =>$mailto,
Subject =>'Mail server virus definition update',
Type =>'TEXT',
Data =>$report
);
MIME::Lite->send('smtp', $smtpserver, Timeout=>60);
$msg->send;
}
exit 0;
# uvscan --version reports...
# "Virus data file v4119 created Feb 03 2001"
# &checkuvscanver returns the version of the data files
#
sub checkuvscanver {
if (`$uvscan_directory/uvscan --version` =~
/Virus data file v([0-9]+) created/) {
return $1;
}
}
If uvscan seems to hang when scanning, try adding the following to mimedefang-filter (near the top, with the other variable declarations):
# Force uvscan to use old thread library
$Features{'Virus:NAI'} = 'LD_ASSUME_KERNEL=2.4.1 /usr/local/bin/uvscan';
Create a new user and group named defang for MIMEDefang.
/usr/sbin/useradd -r -s /sbin/nologin defangCd to the /tmp directory.
The latest source is available from http://www.mimedefang.org/. This example uses version 2.75.
Download the MIMEDefang source at http://www.mimedefang.org/static/mimedefang-2.75.tar.gz.
Unpack the source:
tar xvzf mimedefang-2.75.tar.gzRemove the source:
rm mimedefang-2.75.tar.gzCd into the mimedefang-2.75 directory.
Install the source:
./configure make su -c 'make install'Copy the init script from the examples directory to your init directory.
su -c 'cp examples/init-script /etc/init.d/mimedefang'Cd to the /tmp directory.
Remove the source directory:
rm -rf mimedefang-2.75
Incoming e-mail is handled as follows:
1) For each incoming message, mimedefang creates a temporary directory, makes it the current directory, and splits the message into parts and saves the parts in various files in the directory.
The directory contains the following files:
INPUTMSG A file containing the complete input e-mail message, including
headers.
HEADERS A file containing just the headers, one per line. Headers which
are continued over several lines in the original message are
collapsed into a single line in this file.
COMMANDS A file containing a list of commands. Each command is a single
letter and may be followed by arguments. Each command is on its
own line.
Additional files containing the message body (text and/or HTML) and any
attachments are also created.
When the end of the message is received, mimedefang executes the following command:
/usr/bin/perl /usr/local/bin/mimedefang.pl dir(If you are using mimedefang-multiplexor, the multiplexor manages a pool of persistent Perl processes, and mimedefang itself does not start a Perl interpreter.)
The single argument dir is the temporary directory in which the message information has been saved.
mimedefang.pl loads mimedefang-filter and begins operations on the files in this directory.
2) If the file /etc/mail/mimedefang-filter.pl defines a Perl function called filter_begin, it is called with no arguments. Any return value is ignored.
3) For each leaf part of the mail message, filter is called with four arguments: entity, a MIME::Entity object; fname, the suggested filename taken from the MIME Content-Disposition header; ext, the file extension, and type, the MIME Content-Type value. For each non-leaf part of the mail message, filter_multipart is called with the same four arguments as filter. A non-leaf part of a message is a part which contains nested parts. Such a part has no useful body, but you should still perform filename checks to check for viruses which use malformed MIME to masquerade as non-leaf parts (like message/rfc822). In general, any action you perform in filter_multipart applies to the part itself and any contained parts.
Note that both filter and filter_multipart are optional. If you do not define them, a default function that simply accepts each part is used.
4) After all parts have been processed, the function filter_end is called if it has been defined. It is passed a single argument consisting of the (possibly modified) MIME::Entity object representing the message about to be delivered.
When filter_begin, filter, filter_multipart, or filter_end decide how to dispose of a message or a part, each can call one or more action_ subroutines. Each action_ subroutine is appropriate for particular filter sections (i.e. an action_ subroutine that only works on individual parts works only in filter, not in filter_begin or filter_end). Some of the action subroutines are:
action_accept() - Accept the part.
action_rebuild() - Rebuild the mail body, even if mimedefang thinks no changes were made. Normally, mimedefang does not alter a message if no changes were made. action_rebuild may be used if you make changes to entities directly (by manipulating the MIME::Head, for example.) Unless you call action_rebuild, mimedefang will be unaware of the changes. Note that all the built-in action... routines which change a message implicitly call action_rebuild.
action_add_header($hdr, $val) - Add a header from the message. This can be used in filter_begin or filter_end. The $hdr component is the header name without the colon, and the $val is the header value. For example, to add the header:
X-MyHeader: A nice piece of text
use:
action_add_header("X-MyHeader", "A nice piece of text");
action_change_header($hdr, $val, $index) - Changes an existing header in the message. This can be used in filter_begin or filter_end. The $hdr parameter is the header name without the colon, and $val is the header value. If the header does not exist, then a header with the given name and value is added. The $index parameter is optional; it defaults to 1. If you supply it, then the $index'th occurrence of the header is changed, if there is more than one header with the same name. (This is common with the Received: header, for example.)
action_insert_header($hdr, $val, $index) - Add a header to the message in the specified position $index. A position of 0 specifies that the header should be prepended before existing headers. This can be used in filter_begin or filter_end. The $hdr component is the header name without the colon, and the $val is the header value.
action_delete_header($hdr, $index) - Deletes an existing header in the message. This can be used in filter_begin or filter_end. The $hdr parameter is the header name without the colon.
The $index parameter is optional; it defaults to 1. If you supply it, then the $index'th occurrence of the header is deleted, if there is more than one header with the same name.
action_delete_all_headers($hdr) - Deletes all headers with the specified name. This can be used in filter_begin or filter_end. The $hdr parameter is the header name without the colon.
action_drop() - Drop the part. If called from filter_multipart, drops all contained parts also.
action_drop_with_warning($msg) - Drop the part, but add the warning $msg to the e-mail message. If called from filter_multipart, drops all contained parts also.
action_accept_with_warning($msg) - Accept the part, but add the warning $msg to the e-mail message.
action_replace_with_warning($msg) - Drop the part and replace it with a text part $msg. If called from filter_multipart, drops all contained parts also.
action_replace_with_url($entity, $doc_root, $base_url, $msg, [$cd_data]) - Drop the part, but save it in a unique location under $doc_root. The part is replaced with the text message $msg. The string "_URL_" in $msg is replaced with $base_url/something, which can be used to retrieve the message.
You should not use this function in filter_multipart.
This action is intended for stripping large parts out of the message and replacing them to a link on a Web server. Here's how you would use it in filter():
$size = (stat($entity->bodyhandle->path))[7];
if ($size > 1000000) {
return action_replace_with_url($entity,
"/home/httpd/html/mail_parts",
"http://mailserver.company.com/mail_parts",
"The attachment was larger than 1,000,000 bytes.\n" .
"It was removed, but may be accessed at this URL:\n\n" .
"\t_URL_\n");
}
This example moves attachments greater than 1,000,000 bytes into /home/httpd/html/mail_parts and replaces them with a link. The directory should be accessible via a Web server at http://mailserver.company.com/mail_parts.
The generated name is created by performing a SHA1 hash of the part and adding the extension to the ASCII-HEX representation of the hash. If many different e-mails are sent containing an identical large part, only one copy of the part is stored, regardless of the number of senders or recipients.
For privacy reasons, you must turn off Web server indexing in the directory in which you place mail parts, or anyone will be able to read them. If indexing is disabled, an attacker would have to guess the SHA1 hash of a part in order to read it.
Optionally, a fifth argument can supply data to be saved into a hidden dot filename based on the generated name. This data can then be read in on the fly by a CGI script or mod_perl module before serving the file to a web client, and used to add information to the response, such as Content-Disposition data.
action_defang($entity, $name, $fname, $type) - Accept the part, but change its name to $name, its suggested filename to $fname and its MIME type to $type. If $name or $fname are "", then mimedefang.pl generates generic names. Do not use this action in filter_multipart.
If you use action_defang, you must define a subroutine called defang_warning in your filter. This routine takes two arguments: $oldfname (the original name of an attachment) and $fname (the defanged version.) It should return a message telling the user what happened. For example:
sub defang_warning ($$) {
my($oldfname, $fname) = @_;
return
"An attachment named '$oldfname' was converted to '$fname'.\n" .
"To recover the file, right-click on the attachment and Save As\n" .
"'$oldfname'\n";
}
action_external_filter($entity, $cmd) - Run an external UNIX command $cmd. This command must read the part from the file ./FILTERINPUT and leave the result in ./FILTEROUTPUT. If the command executes successfully, returns 1, otherwise 0. You can test the return value and call another action_ if the filter failed. Do not use this action in filter_multipart.
action_quarantine($entity, $msg) - Drop and quarantine the part, but add the warning $msg to the e-mail message.
action_quarantine_entire_message() - Quarantines the entire message in a quarantine directory on the mail server, but does not otherwise affect disposition of the message. If "$msg" is non-empty, it is included in any administrator notification.
action_sm_quarantine($reason) - Quarantines a message in the Sendmail mail queue using the new QUARANTINE facility of Sendmail 8.13. Consult the Sendmail documentation for details about this facility. If you use action_sm_quarantine with a version of Sendmail that lacks the QUARANTINE facility, mimedefang will log an error message and not quarantine the message.
action_bounce($reply, $code, $dsn) - Bounce the entire e-mail message with the one-line error message $reply. If the optional $code and $dsn arguments are supplied, they specify the numerical SMTP reply code and the extended status code (DSN code). If the codes you supply do not make sense for a bounce, they are replaced with "554" and "5.7.1" respectively.
action_bounce merely makes a note that the message is to be bounced; remaining parts are still processed. If action_bounce is called for more than one part, the mail is bounced with the message in the final call to action_bounce. You can profitably call action_quarantine followed by action_bounce if you want to keep a copy of the offending part. Note that the message is not bounced immediately; rather, remaining parts are processed and the message is bounced after all parts have been processed.
WARNING: action_bounce() may generate spurious bounce messages if the sender address is faked. This is a particular problem with viruses. However, we believe that on balance, it's better to bounce a virus than to silently discard it. It's almost never a good idea to hide a problem.
action_tempfail($msg, $code, $dsn) - Cause an SMTP "temporary failure" code to be returned, so the sending mail relay requeues the message and tries again later. The message $msg is included with the temporary failure code. If the optional $code and $dsn arguments are supplied, they specify the numerical SMTP reply code and the extended status code (DSN code). If the codes you supply do not make sense for a temporary failure, they are replaced with "450" and "4.7.1" respectively.
action_discard() - Silently discard the message, notifying nobody. You can profitably call action_quarantine followed by action_discard if you want to keep a copy of the offending part. Note that the message is not discarded immediately; rather, remaining parts are processed and the message is discarded after all parts have been processed.
action_notify_sender($message) - This action sends an e-mail back to the original sender with the indicated message. You may call another action after this one. If action_notify_sender is called more than once, the messages are accumulated into a single e-mail message -- at most one notification message is sent per incoming message. The message should be terminated with a newline.
action_notify_administrator($message) - This action e-mails the MIMEDefang administrator the supplied message. You may call another action after this one; action_notify_administrator does not affect mail processing. If action_notify_administrator is called more than once, the messages are accumulated into a single e- mail message -- at most one notification message is sent per incoming message. The message should be terminated with a newline.
MIMEDefang installs a working sample filter to /etc/mail/mimedefang-filter, or to /etc/mail/mimedefang-filter.example if mimedefang-filter already exists. To begin with the new sample filter, copy the sample to mimedefang-filter.
cp mimedefang-filter.example mimedefang-filter
$AdminAddress = 'defang-admin@localhost'; $AdminName = "MIMEDefang Administrator's Full Name"; $DaemonAddress = 'postmaster@yourcompany.com';The following optional lines will modify default values. Add any or all if desired.
$DaemonName = 'Your Company Mail Server'; #*********************************************************************** # Set general warning message here. This message is printed before any # specific warning messages in the warning message text attachment. #*********************************************************************** $GeneralWarning = "WARNING: This email violated Your Company's email security policy and\n" . "has been modified. For more information, contact $Administrator.\n\n";
# Reject message; do NOT allow message to reach recipient(s)
return action_bounce("Message rejected; illegal characters in message (per RFC 2821, 2822)");
sub filter ($$$$) {
my($entity, $fname, $ext, $type) = @_;
return if message_rejected(); # Avoid unnecessary work
# Block message/partial parts
if (lc($type) eq "message/partial") {
md_graphdefang_log('message/partial');
action_bounce("MIME type message/partial not accepted here");
return action_discard();
}
if (filter_bad_filename($entity)) {
md_graphdefang_log('bad_filename', $fname, $type);
return action_drop_with_warning("An attachment named $fname was removed from this document as it\nconstituted a security hazard. If you require this document, please contact\nthe sender and arrange an alternate means of receiving it.\n");
}
# eml is bad if it's not multipart
if (re_match($entity, '\.eml')) {
md_graphdefang_log('non_multipart');
return action_drop_with_warning("A non-multipart attachment named $fname was removed from this document as it\nconstituted a security hazard. If you require this document, please contact\nthe sender and arrange an alternate means of receiving it.\n");
}
# Clean up HTML if Anomy::HTMLCleaner is installed.
if ($Features{"HTMLCleaner"}) {
if ($type eq "text/html") {
return anomy_clean_html($entity);
}
}
return action_accept();
}
sub filter_multipart ($$$$) {
my($entity, $fname, $ext, $type) = @_;
return if message_rejected(); # Avoid unnecessary work
if (filter_bad_filename($entity)) {
md_graphdefang_log('bad_filename', $fname, $type);
action_notify_administrator("A MULTIPART attachment of type $type, named $fname was dropped.\n");
return action_drop_with_warning("An attachment of type $type, named $fname was removed from this document as it\nconstituted a security hazard. If you require this document, please contact\nthe sender and arrange an alternate means of receiving it.\n");
}
# eml is bad if it's not message/rfc822
if (re_match($entity, '\.eml') and ($type ne "message/rfc822")) {
md_graphdefang_log('non_rfc822',$fname);
return action_drop_with_warning("A non-message/rfc822 attachment named $fname was removed from this document as it\nconstituted a security hazard. If you require this document, please contact\nthe sender and arrange an alternate means of receiving it.\n");
}
# Block message/partial parts
if (lc($type) eq "message/partial") {
md_graphdefang_log('message/partial');
action_bounce("MIME type message/partial not accepted here");
return;
}
return action_accept();
}
sub filter_end ($) {
my($entity) = @_;
# If you want quarantine reports, uncomment next line
# send_quarantine_notifications();
# IMPORTANT NOTE: YOU MUST CALL send_quarantine_notifications() AFTER
# ANY PARTS HAVE BEEN QUARANTINED. SO IF YOU MODIFY THIS FILTER TO
# QUARANTINE SPAM, REWORK THE LOGIC TO CALL send_quarantine_notifications()
# AT THE END!!!
# No sense doing any extra work
return if message_rejected();
# Spam checks if SpamAssassin is installed
if ($Features{"SpamAssassin"}) {
if (-s "./INPUTMSG" < 100*1024) {
# Only scan messages smaller than 100kB. Larger messages
# are extremely unlikely to be spam, and SpamAssassin is
# dreadfully slow on very large messages.
my($hits, $req, $names, $report) = spam_assassin_check();
my($score);
if ($hits < 40) {
$score = "*" x int($hits);
} else {
$score = "*" x 40;
}
# We add a header which looks like this:
# X-Spam-Score: 6.8 (******) NAME_OF_TEST,NAME_OF_TEST
# The number of asterisks in parens is the integer part
# of the spam score clamped to a maximum of 40.
# MUA filters can easily be written to trigger on a
# minimum number of asterisks...
if ($hits >= $req) {
action_change_header("X-Spam-Score", "$hits ($score) $names");
md_graphdefang_log('spam', $hits, $RelayAddr);
# If you find the SA report useful, add it, I guess...
action_add_part($entity, "text/plain", "-suggest",
"$report\n",
"SpamAssassinReport.txt", "inline");
} else {
# Delete any existing X-Spam-Score header?
action_delete_header("X-Spam-Score");
}
}
}
# I HATE HTML MAIL! If there's a multipart/alternative with both
# text/plain and text/html parts, nuke the text/html. Thanks for
# wasting our disk space and bandwidth...
# If you want to strip out HTML parts if there is a corresponding
# plain-text part, uncomment the next line.
# remove_redundant_html_parts($entity);
md_graphdefang_log('mail_in');
# Deal with malformed MIME.
# Some viruses produce malformed MIME messages that are misinterpreted
# by mail clients. They also might slip under the radar of MIMEDefang.
# If you are worried about this, you should canonicalize all
# e-mail by uncommenting the action_rebuild() line. This will
# force _all_ messages to be reconstructed as valid MIME. It will
# increase the load on your server, and might break messages produced
# by marginal software. Your call.
# action_rebuild();
}
Another common use of filter_end is the insertion of boilerplate text into a
message. The append_text_boilerplate and append_html_boilerplate functions
append text to the first text/plain or text/html part found in the message.
These functions would be added inside the existing filter_end:
append_text_boilerplate($entity, "All information contained in " .
"this email is confidential and may be used by the intended " .
"recipient only.", 0);
append_html_boilerplate($entity, "All information contained in " .
"this email is confidential and may be used by the intended " .
"recipient only.", 0);
mimedefang.pl -testYou can also test other filters with the -f option:
mimedefang.pl -f test-filter -testThis is useful (and recommended) when writing a new filter for a production server, so that the working filter can be left in place.
Start sendmail:
/etc/init.d/sendmail start
# -*- Perl -*-
#***********************************************************************
#
# mimedefang-filter
#
# Suggested minimum-protection filter for Microsoft Windows clients, plus
# SpamAssassin checks if SpamAssassin is installed.
#
# Copyright (C) 2002 Roaring Penguin Software Inc.
#
# This program may be distributed under the terms of the GNU General
# Public License, Version 2, or (at your option) any later version.
#
# $Id$
#***********************************************************************
#***********************************************************************
# Set administrator's e-mail address here. The administrator receives
# quarantine messages and is listed as the contact for site-wide
# MIMEDefang policy. A good example would be 'defang-admin@mydomain.com'
#***********************************************************************
$AdminAddress = 'postmaster@localhost';
$AdminName = "MIMEDefang Administrator's Full Name";
#***********************************************************************
# Set the e-mail address from which MIMEDefang quarantine warnings and
# user notifications appear to come. A good example would be
# 'mimedefang@mydomain.com'. Make sure to have an alias for this
# address if you want replies to it to work.
#***********************************************************************
$DaemonAddress = 'mimedefang@localhost';
#***********************************************************************
# If you set $AddWarningsInline to 1, then MIMEDefang tries *very* hard
# to add warnings directly in the message body (text or html) rather
# than adding a separate "WARNING.TXT" MIME part. If the message
# has no text or html part, then a separate MIME part is still used.
#***********************************************************************
$AddWarningsInline = 0;
#***********************************************************************
# To enable syslogging of virus and spam activity, add the following
# to the filter:
# md_graphdefang_log_enable();
# You may optionally provide a syslogging facility by passing an
# argument such as: md_graphdefang_log_enable('local4'); If you do this, be
# sure to setup the new syslog facility (probably in /etc/syslog.conf).
# An optional second argument causes a line of output to be produced
# for each recipient (if it is 1), or only a single summary line
# for all recipients (if it is 0.) The default is 1.
# Comment this line out to disable logging.
#***********************************************************************
md_graphdefang_log_enable('mail', 1);
#***********************************************************************
# Uncomment this to block messages with more than 50 parts. This will
# *NOT* work unless you're using Roaring Penguin's patched version
# of MIME tools, version MIME-tools-5.411a-RP-Patched-02 or later.
#
# WARNING: DO NOT SET THIS VARIABLE unless you're using at least
# MIME-tools-5.411a-RP-Patched-02; otherwise, your filter will fail.
#***********************************************************************
# $MaxMIMEParts = 50;
#***********************************************************************
# Set various stupid things your mail client does below.
#***********************************************************************
# Set the next one if your mail client cannot handle multiple "inline"
# parts.
$Stupidity{"NoMultipleInlines"} = 0;
# Detect and load Perl modules
detect_and_load_perl_modules();
# This procedure returns true for entities with bad filenames.
sub filter_bad_filename {
my($entity) = @_;
my($bad_exts, $re);
# Bad extensions
$bad_exts = '(ade|adp|app|asd|asf|asx|bas|bat|chm|cmd|com|cpl|crt|dll|exe|fxp|hlp|hta|hto|inf|ini|ins|isp|jse?|lib|lnk|mdb|mde|msc|msi|msp|mst|ocx|pcd|pif|prg|reg|scr|sct|sh|shb|shs|sys|url|vb|vbe|vbs|vcs|vxd|wmd|wms|wmz|wsc|wsf|wsh|\{[^\}]+\})';
# Do not allow:
# - CLSIDs {foobarbaz}
# - bad extensions (possibly with trailing dots) at end
$re = '\.' . $bad_exts . '\.*$';
return 1 if (re_match($entity, $re));
# Look inside ZIP files
if (re_match($entity, '\.zip$') and
$Features{"Archive::Zip"}) {
my $bh = $entity->bodyhandle();
if (defined($bh)) {
my $path = $bh->path();
if (defined($path)) {
return re_match_in_zip_directory($path, $re);
}
}
}
return 0;
}
#***********************************************************************
# %PROCEDURE: filter_begin
# %ARGUMENTS:
# $entity -- the parsed MIME::Entity
# %RETURNS:
# Nothing
# %DESCRIPTION:
# Called just before e-mail parts are processed
#***********************************************************************
sub filter_begin {
my($entity) = @_;
# ALWAYS drop messages with suspicious chars in headers
if ($SuspiciousCharsInHeaders) {
md_graphdefang_log('suspicious_chars');
# action_quarantine_entire_message("Message quarantined because of suspicious characters in headers");
# Do NOT allow message to reach recipient(s)
return action_discard();
}
# Copy original message into work directory as an "mbox" file for
# virus-scanning
md_copy_orig_msg_to_work_dir_as_mbox_file();
# Scan for viruses if any virus-scanners are installed
my($code, $category, $action) = message_contains_virus();
# Lower level of paranoia - only looks for actual viruses
$FoundVirus = ($category eq "virus");
# Higher level of paranoia - takes care of "suspicious" objects
# $FoundVirus = ($action eq "quarantine");
if ($FoundVirus) {
md_graphdefang_log('virus', $VirusName, $RelayAddr);
md_syslog('warning', "Discarding because of virus $VirusName");
return action_discard();
}
if ($action eq "tempfail") {
action_tempfail("Problem running virus-scanner");
md_syslog('warning', "Problem running virus scanner: code=$code, category=$category, action=$action");
}
}
#***********************************************************************
# %PROCEDURE: filter
# %ARGUMENTS:
# entity -- a Mime::Entity object (see MIME-tools documentation for details)
# fname -- the suggested filename, taken from the MIME Content-Disposition:
# header. If no filename was suggested, then fname is ""
# ext -- the file extension (everything from the last period in the name
# to the end of the name, including the period.)
# type -- the MIME type, taken from the Content-Type: header.
#
# NOTE: There are two likely and one unlikely place for a filename to
# appear in a MIME message: In Content-Disposition: filename, in
# Content-Type: name, and in Content-Description. If you are paranoid,
# you will use the re_match and re_match_ext functions, which return true
# if ANY of these possibilities match. re_match checks the whole name;
# re_match_ext checks the extension. See the sample filter below for usage.
# %RETURNS:
# Nothing
# %DESCRIPTION:
# This function is called once for each part of a MIME message.
# There are many action_*() routines which can decide the fate
# of each part; see the mimedefang-filter man page.
#***********************************************************************
sub filter {
my($entity, $fname, $ext, $type) = @_;
return if message_rejected(); # Avoid unnecessary work
# Block message/partial parts
if (lc($type) eq "message/partial") {
md_graphdefang_log('message/partial');
action_bounce("MIME type message/partial not accepted here");
return action_discard();
}
if (filter_bad_filename($entity)) {
md_graphdefang_log('bad_filename', $fname, $type);
return action_drop_with_warning("An attachment named $fname was removed from this document as it\nconstituted a security hazard. If you require this document, please contact\nthe sender and arrange an alternate means of receiving it.\n");
}
return action_accept();
}
#***********************************************************************
# %PROCEDURE: filter_multipart
# %ARGUMENTS:
# entity -- a Mime::Entity object (see MIME-tools documentation for details)
# fname -- the suggested filename, taken from the MIME Content-Disposition:
# header. If no filename was suggested, then fname is ""
# ext -- the file extension (everything from the last period in the name
# to the end of the name, including the period.)
# type -- the MIME type, taken from the Content-Type: header.
# %RETURNS:
# Nothing
# %DESCRIPTION:
# This is called for multipart "container" parts such as message/rfc822.
# You cannot replace the body (because multipart parts have no body),
# but you should check for bad filenames.
#***********************************************************************
sub filter_multipart {
my($entity, $fname, $ext, $type) = @_;
return if message_rejected(); # Avoid unnecessary work
if (filter_bad_filename($entity)) {
md_graphdefang_log('bad_filename', $fname, $type);
action_notify_administrator("A MULTIPART attachment of type $type, named $fname was dropped.\n");
return action_drop_with_warning("An attachment of type $type, named $fname was removed from this document as it\nconstituted a security hazard. If you require this document, please contact\nthe sender and arrange an alternate means of receiving it.\n");
}
# Block message/partial parts
if (lc($type) eq "message/partial") {
md_graphdefang_log('message/partial');
action_bounce("MIME type message/partial not accepted here");
return;
}
return action_accept();
}
#***********************************************************************
# %PROCEDURE: defang_warning
# %ARGUMENTS:
# oldfname -- the old file name of an attachment
# fname -- the new "defanged" name
# %RETURNS:
# A warning message
# %DESCRIPTION:
# This function customizes the warning message when an attachment
# is defanged.
#***********************************************************************
sub defang_warning {
my($oldfname, $fname) = @_;
return
"An attachment named '$oldfname' was converted to '$fname'.\n" .
"To recover the file, right-click on the attachment and Save As\n" .
"'$oldfname'\n";
}
# If SpamAssassin found SPAM, append report. We do it as a separate
# attachment of type text/plain
sub filter_end {
my($entity) = @_;
# If you want quarantine reports, uncomment next line
# send_quarantine_notifications();
# IMPORTANT NOTE: YOU MUST CALL send_quarantine_notifications() AFTER
# ANY PARTS HAVE BEEN QUARANTINED. SO IF YOU MODIFY THIS FILTER TO
# QUARANTINE SPAM, REWORK THE LOGIC TO CALL send_quarantine_notifications()
# AT THE END!!!
# No sense doing any extra work
return if message_rejected();
# Spam checks if SpamAssassin is installed
if ($Features{"SpamAssassin"}) {
if (-s "./INPUTMSG" < 100*1024) {
# Only scan messages smaller than 100kB. Larger messages
# are extremely unlikely to be spam, and SpamAssassin is
# dreadfully slow on very large messages.
my($hits, $req, $names, $report) = spam_assassin_check();
my($score);
if ($hits < 40) {
$score = "*" x int($hits);
} else {
$score = "*" x 40;
}
# We add a header which looks like this:
# X-Spam-Score: 6.8 (******) NAME_OF_TEST,NAME_OF_TEST
# The number of asterisks in parens is the integer part
# of the spam score clamped to a maximum of 40.
# MUA filters can easily be written to trigger on a
# minimum number of asterisks...
if ($hits >= $req) {
action_change_header("X-Spam-Score", "$hits ($score) $names");
md_graphdefang_log('spam', $hits, $RelayAddr);
# If you find the SA report useful, add it, I guess...
action_add_part($entity, "text/plain", "-suggest",
"$report\n",
"SpamAssassinReport.txt", "inline");
} else {
# Delete any existing X-Spam-Score header?
action_delete_header("X-Spam-Score");
}
}
}
# I HATE HTML MAIL! If there's a multipart/alternative with both
# text/plain and text/html parts, nuke the text/html. Thanks for
# wasting our disk space and bandwidth...
# If you want to strip out HTML parts if there is a corresponding
# plain-text part, uncomment the next line.
# remove_redundant_html_parts($entity);
md_graphdefang_log('mail_in');
# Deal with malformed MIME.
# Some viruses produce malformed MIME messages that are misinterpreted
# by mail clients. They also might slip under the radar of MIMEDefang.
# If you are worried about this, you should canonicalize all
# e-mail by uncommenting the action_rebuild() line. This will
# force _all_ messages to be reconstructed as valid MIME. It will
# increase the load on your server, and might break messages produced
# by marginal software. Your call.
# action_rebuild();
}
# DO NOT delete the next line, or Perl will complain.
1;
/etc/init.d/mimedefang reread
This document is no longer available on Microsoft's web site. An archived version is at https://web.archive.org/web/20031002005744/http://support.microsoft.com/default.aspx?scid=kb;en-us;290497.
Another document providing similar information is at http://support.microsoft.com/kb/883260/.
According to Microsoft, "The following list contains attachments that are considered unsafe:"
File Extension Description --------- -------------------------------------------- ADE Microsoft Access project extension ADP Microsoft Access project ASX Windows Media Audio / Video BAS Microsoft Visual Basic class module BAT Batch file CHM Compiled HTML Help file CMD Microsoft Windows NT Command script COM Microsoft MS-DOS program CPL Control Panel extension CRT Security certificate EXE Program HLP Help file HTA HTML program INF Setup Information INS Internet Naming Service ISP Internet Communication settings JS JScript File JSE JScript Encoded Script file LNK Shortcut MDA Microsoft Access add-in program MDB Microsoft Access program MDE Microsoft Access MDE database MDT Microsoft Access workgroup information MDW Microsoft Access workgroup information MDZ Microsoft Access wizard program MSC Microsoft Common Console document MSI Microsoft Windows Installer package MSP Microsoft Windows Installer patch MST Microsoft Windows Installer transform, Microsoft Visual Test source file OPS Office XP settings PCD Photo CD Image, Microsoft Visual compiled script PIF Shortcut to MS-DOS program PRF Microsoft Outlook profile settings REG Registration entries SCF Windows Explorer command SCR Screen saver SCT Windows Script Component SHB Shell Scrap object SHS Shell Scrap object URL Internet shortcut VB VBScript file VBE VBScript Encoded script file VBS VBScript file WSC Windows Script Component WSF Windows Script file WSH Windows Scripting Host Settings file
GNU Free Documentation License
Version 1.2, November 2002
Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other
functional and useful document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.
This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense. It
complements the GNU General Public License, which is a copyleft
license designed for free software.
We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does. But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book. We recommend this License
principally for works whose purpose is instruction or reference.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium, that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License. Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein. The "Document", below,
refers to any such manual or work. Any member of the public is a
licensee, and is addressed as "you". You accept the license if you
copy, modify or distribute the work in a way requiring permission
under copyright law.
A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
A "Secondary Section" is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject. (Thus, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.
The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License. If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant. The Document may contain zero
Invariant Sections. If the Document does not identify any Invariant
Sections then there are none.
The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License. A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification. Examples of
transparent image formats include PNG, XCF and JPG. Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.
The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language. (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements",
"Dedications", "Endorsements", or "History".) To "Preserve the Title"
of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.
The Document may include Warranty Disclaimers next to the notice which
states that this License applies to the Document. These Warranty
Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has
no effect on the meaning of this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License. You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute. However, you may accept
compensation in exchange for copies. If you distribute a large enough
number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and
you may publicly display copies.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
you as the publisher of these copies. The front cover must present
the full title with all words of the title equally prominent and
visible. You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
public has access to download using public-standard network protocols
a complete Transparent copy of the Document, free of added material.
If you use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to ensure
that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.
It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to give
them a chance to provide you with an updated version of the Document.
4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it. In addition, you must do these things in the Modified Version:
A. Use in the Title Page (and on the covers, if any) a title distinct
from that of the Document, and from those of previous versions
(which should, if there were any, be listed in the History section
of the Document). You may use the same title as a previous version
if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified
Version, together with at least five of the principal authors of the
Document (all of its principal authors, if it has fewer than five),
unless they release you from this requirement.
C. State on the Title page the name of the publisher of the
Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice
giving the public permission to use the Modified Version under the
terms of this License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections
and required Cover Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled "History", Preserve its Title, and add
to it an item stating at least the title, year, new authors, and
publisher of the Modified Version as given on the Title Page. If
there is no section Entitled "History" in the Document, create one
stating the title, year, authors, and publisher of the Document as
given on its Title Page, then add an item describing the Modified
Version as stated in the previous sentence.
J. Preserve the network location, if any, given in the Document for
public access to a Transparent copy of the Document, and likewise
the network locations given in the Document for previous versions
it was based on. These may be placed in the "History" section.
You may omit a network location for a work that was published at
least four years before the Document itself, or if the original
publisher of the version it refers to gives permission.
K. For any section Entitled "Acknowledgements" or "Dedications",
Preserve the Title of the section, and preserve in the section all
the substance and tone of each of the contributor acknowledgements
and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document,
unaltered in their text and in their titles. Section numbers
or the equivalent are not considered part of the section titles.
M. Delete any section Entitled "Endorsements". Such a section
may not be included in the Modified Version.
N. Do not retitle any existing section to be Entitled "Endorsements"
or to conflict in title with any Invariant Section.
O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant. To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.
You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.
You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version. Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity. If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy. If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled "History"
in the various original documents, forming one section Entitled
"History"; likewise combine any sections Entitled "Acknowledgements",
and any sections Entitled "Dedications". You must delete all sections
Entitled "Endorsements".
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute
it individually under this License, provided you insert a copy of this
License into the extracted document, and follow this License in all
other respects regarding verbatim copying of that document.
7. AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an "aggregate" if the copyright
resulting from the compilation is not used to limit the legal rights
of the compilation's users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.
8. TRANSLATION
Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers. In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.
If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License. Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License. However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions
of the GNU Free Documentation License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns. See
http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation. If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.
ADDENDUM: How to use this License for your documents
To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
license notices just after the title page:
Copyright (c) YEAR YOUR NAME.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the "with...Texts." line with this:
with the Invariant Sections being LIST THEIR TITLES, with the
Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
If you have Invariant Sections without Cover Texts, or some other
combination of the three, merge those two alternatives to suit the
situation.
If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
free software license, such as the GNU General Public License,
to permit their use in free software.