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 $RETVALEnable 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.