[Mimedefang] warning.txt appear instead of message body

Marco Berizzi pupilla at hotmail.com
Thu Sep 12 08:20:08 EDT 2002


Hi,

I have a problem with my gateway MD 2.20/Sendmail 8.12.6 and my mail
server M$ Exchange 5.5 Sp3/LookOut 2000

If I send a simple mail (text format) with some not permitted
attachment, MD remove the dangerous attach and add to the e-mail the
warning.txt file. On the client side (LookOut 2000 / netscape 6.2.1), on
the message body appear the contents of the file warning.txt and the
original body is put on a file called ATTxxxx.txt (if the original
message was text format) or an untitled attach (with two attach inside
it called ATTxxxx.txt and ATTxxxx.htm) if the original message was in
HTML format.
As a workaround I have set $AddWarningsInline = 1

With the same filter, which is a little modified version of sugg.
minimun filter for windoze, version 2.15 of MD was OK.
Any idea?

My env.
Slackware 8.1 kernel 2.4.19
gcc 2.95.3
glibc 2.2.5
perl 5.6.1
sendmail 8.12.6
SA 2.41
MD 2.20
Anomy 1.49
Digest-SHA1-2.01
File-Scan-0.35
HTML-Parser-3.26
HTML-Tagset-3.03
IO-stringy-2.108
MailTools-1.15
MIME-Base64-2.12
MIME-tools-5.411a

Follow my filter:

# -*- 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: suggested-minimum-filter-for-windows-clients,v 1.46 2002/09/06
12:22:49 dfs Exp $

#***********************************************************************

#***********************************************************************

# 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 at mydomain.com'

#***********************************************************************

#$AdminAddress = 'postmaster at localhost';

$AdminAddress = 'postmaster at XXX.it';

#$AdminName = "MIMEDefang Administrator's Full Name";

$AdminName = "Marco Berizzi";

#***********************************************************************

# Set the e-mail address from which MIMEDefang quarantine warnings and

# user notifications appear to come. A good example would be

# 'mimedefang at mydomain.com'. Make sure to have an alias for this

# address if you want replies to it to work.

#***********************************************************************

#$DaemonAddress = 'mimedefang at localhost';

$DaemonAddress = 'postmaster at XXX.it';

#***********************************************************************

# Set the general warning when MIMEDefang alter a message

#***********************************************************************

$GeneralWarning =

"ATTENZIONE: Questa e-mail e` stata modificata da\n" .

"MIMEDefang. Per ulteriori informazioni e/o chiarimenti\n" .

"contattare l'amministratore $AdminName esclusivamente\n" .

"tramite posta elettronica all'indirizzo <$AdminAddress>\n" .

"Seguono i dettagli della modifica\n";

#***********************************************************************

# 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;

#***********************************************************************

# Set various stupid things your mail client does below.

#***********************************************************************

# Set the next one if your mail client cannot handle nested multipart

# messages. DO NOT set this lightly; it will cause action_add_part to

# work rather strangely. Leave it at zero, even for MS Outlook, unless

# you have serious problems.

$Stupidity{"flatten"} = 0;

# Set the next one if your mail client cannot handle multiple "inline"

# parts.

$Stupidity{"NoMultipleInlines"} = 0;

# Local network skip Spam Assassin

$LocalNetworks = '172\.17\.1|172\.18\.1|172\.21\.1|172\.22\.1';

# This is a list of permitted ext when the message is larger than

# $MaxOutSize

$MaxOutSize = 100*1024;

sub filter_good_filename ($) {

my($entity) = @_;

my($good_exts, $re);

# Good extensions

$good_exts = '\.(gz|zip|rar|bz2|tgz|tbz)$';

$re = $good_exts;

return re_match($entity, $re);

}

# 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|ht
a|hto|inf|ini|ins|isp|jse?|lib|lnk|mdb|mde|msc|msi|msp|mst|ocx|pcd|pif|p
rg|reg|scr|sct|sh|shb|shs|sys|url|vb|vbe|vbs|vcs|vxd|wmd|wms|wmz|wsc|wsf
|wsh|\{)';

$bad_exts =
'(avi|asf|mp3|mpg|mpe|mpeg|mov|mng|ade|adp|app|asd|asf|asx|bas|bat|chm|c
md|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|vb
e|vbs|vcs|vxd|wmd|wms|wmz|wsc|wsf|wsh|\{)';


# Do not allow:

# - curlies

# - bad extensions (possibly with trailing dots) at end or

# followed by non-alphanum

$re = '\.' . $bad_exts . '\.*([^-A-Za-z0-9_.,]|$)';

return re_match($entity, $re);

}

# Scan for a virus using the first supported virus scanner we find.

sub message_contains_virus () {

return message_contains_virus_filescan() if
($Features{'Virus:FileScan'});

return (wantarray ? (0, 'ok', 'ok') : 0);

}

# Scan for a virus using the first supported virus scanner we find.

sub entity_contains_virus ($) {

my($e) = @_;

return entity_contains_virus_filescan($e) if
($Features{'Virus:FileScan'});

return (wantarray ? (0, 'ok', 'ok') : 0);

}

#***********************************************************************

# %PROCEDURE: filter_begin

# %ARGUMENTS:

# None

# %RETURNS:

# Nothing

# %DESCRIPTION:

# Called just before e-mail parts are processed

#***********************************************************************

sub filter_begin () {

# ALWAYS drop messages with suspicious chars in headers

if ($SuspiciousCharsInHeaders) {

action_quarantine_entire_message();

action_notify_administrator("Message quarantined because of suspicious
characters in headers");

# Do NOT allow message to reach recipient(s)

return action_discard();

}

$LocalRelay = ($RelayAddr =~ /^(127.0.0.1|$LocalNetworks)/);

# Scan for viruses if any virus-scanners are installed

my($code, $category, $action) = message_contains_virus();

$FoundVirus = ($category eq "virus");

}

#***********************************************************************

# %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

if (!$LocalRelay) {

# Reject Korean Mail

$head = $entity->head;

$charset = $head->mime_attr("content-type.charset");

if (defined($charset)) {

$charset =~ tr/A-Z/a-z/;

if ($charset eq "ks_c_5601-1987" or

$charset eq "euc-kr") {

action_notify_administrator("Spam from Korea not accepted.");

return action_bounce("Spam from Korea not accepted.");

}

}

# Virus scan

if ($FoundVirus) {

my($code, $category, $action);

$VirusScannerMessages = "";

($code, $category, $action) = entity_contains_virus($entity);

if ($category eq "virus") {

#return action_quarantine($entity, "A known virus was discovered and
deleted. Virus-scanner messages follow:\n$VirusScannerMessages\n\n");

action_notify_administrator("A known virus was discovered and deleted.
Virus-scanner messages follow:\n$VirusScannerMessages\n\n");

return action_drop_with_warning("Un virus e' stato scoperto e
cancellato. Segue il messaggio
dell'antivirus:\n$VirusScannerMessages\n\n");

}

}

# Mangling attachment

if (filter_bad_filename($entity)) {

#return action_quarantine($entity, "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");

action_notify_administrator("An attachment named $fname was removed from
this document as it\nconstituted a security hazard.\n");

return action_drop_with_warning("Un allegato chiamato $fname e' stato
rimosso da questo documento\ndato che si tratta di un allegato
pericoloso. Se hai bisogno di questo\ndocumento contatta il
mittente.\n");

}

# eml is bad if it's not multipart

if (re_match($entity, '\.eml')) {

#return action_quarantine($entity, "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");

action_notify_administrator("A non-multipart attachment named $fname was
removed from this document as it\nconstituted a security hazard.\n");

return action_drop_with_warning("Un allegato non-multipart chiamato
$fname e' stato rimosso da questo documento\ndato che si tratta di un
allegato pericoloso. Se hai bisogno di questo\ndocumento contatta il
mittente.\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();

}

if ($LocalRelay) {

# Usually people break my balls because I restrict the

# message size. OK: I have changed the limit.

# Italian people are lazy. I have never seen a compressed

# attach in an e-mail, so this time ball-breakers *MUST* compress the

# attach if the message is bigger than $MaxOutSize

if (-s "./INPUTMSG" > $MaxOutSize) {

if (filter_good_filename($entity) or ($type =~ m+^text/+) or ($type eq
"text")) {

return action_accept();

} else {

#action_notify_administrator("Il messaggio contiene allegati non
zippati");

return action_bounce("Il messaggio contiene allegati non zippati");

}

}

# Virus scan

if ($FoundVirus) {

my($code, $category, $action);

$VirusScannerMessages = "";

($code, $category, $action) = entity_contains_virus($entity);

if ($category eq "virus") {

#return action_quarantine($entity, "A known virus was discovered and
deleted. Virus-scanner messages follow:\n$VirusScannerMessages\n\n");

action_notify_administrator("Il messaggio e' stato rifiutato perche' e`
presente un Virus:\n$VirusScannerMessages\n\n");

return action_bounce("Il messaggio e' stato rifiutato perche' e`
presente un Virus");

}

}

# Mangling attachment

if (filter_bad_filename($entity)) {

#action_notify_administrator("Il messaggio e' stato rifiutato perche' e`
presente un allegato pericoloso chiamato $fname");

return action_bounce("Il messaggio e' stato rifiutato perche' e`
presente un allegato pericoloso chiamato $fname");

}

# eml is bad if it's not multipart

if (re_match($entity, '\.eml')) {

#action_notify_administrator("Il messaggio e' stato rifiutato perche' e`
presente un allegato non-multipart chiamato $fname");

return action_bounce("Il messaggio e' stato rifiutato perche' e`
presente un allegato non-multipart chiamato $fname");

}

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) = @_;

if (!$LocalRelay) {

if (filter_bad_filename($entity)) {

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");

return action_drop_with_warning("Un allegato di tipo $type, chiamato
$fname e' stato rimosso da questo documento\ndato che si tratta di un
allegato pericoloso. Se hai bisogno di questo documento\ncontatta il
mittente.\n");

}

# eml is bad if it's not message/rfc822

if (re_match($entity, '\.eml') and ($type ne "message/rfc822")) {

#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");

action_notify_administrator("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");

return action_drop_with_warning("Un allegato di tipo non-message/rfc822,
chiamato $fname e' stato rimosso da questo documento\ndato che si tratta
di un allegato pericoloso. Se hai bisogno di questo documento\ncontatta
il mittente.\n");

}

return action_accept();

}

if ($LocalRelay) {

if (filter_bad_filename($entity)) {

#action_notify_administrator("Message bounced because of A MULTIPART
attachment of type $type, named $fname");

#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");

return action_bounce("Il messaggio e' stato rifiutato perche' contiene
un allegato di tipo $type, chiamato $fname");

}

# eml is bad if it's not message/rfc822

if (re_match($entity, '\.eml') and ($type ne "message/rfc822")) {

#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");

return action_bounce("Il messaggio e' stato rifiutato perche' contiene
un allegato di tipo non-message/rfc822, chiamato $fname");

}

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) = @_;

# No sense doing any extra work

return if message_rejected();

# Spam checks if SpamAssassin is installed

if (!$LocalRelay) {

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();

if ($hits >= $req) {

my($score);

if ($hits < 20) {

$score = "*" x int($hits);

} else {

$score = "*" x 20;

}

# 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 >= 22) {

return action_bounce("We don't accept SPAM");

}

action_change_header("Subject", "***SPAM*** $Subject ($score)");

action_change_header("X-Spam-Score", "$hits ($score) $names");

# If you find the SA report useful, add it, I guess...

action_add_part($entity, "text/plain", "-suggest",

"$report\n",

"SpamAssassinReport.txt", "inline");

}

}

}

}

}

# DO NOT delete the next line, or Perl will complain.

1;




More information about the MIMEDefang mailing list