[Mimedefang] utf-8 issue?
Mark Coetser
mark at tux-edo.co.za
Wed Dec 13 02:25:57 EST 2017
On 12/12/2017 20:03, Dianne Skoll wrote:
> On Tue, 12 Dec 2017 15:43:14 +0200
> Mark Coetser <mark at tux-edo.co.za> wrote:
>
>> Error from multiplexor: ERR No response from slave
>> Reap: slave 1 (pid 15022) exited normally with status 22 (SLAVE DIED
>> UNEXPECTEDLY)
>
> I've never seen this before. I'm also not convinced it's related
> to the UTF-8 issue. Could you post the exact filter you are using?
>
> I'm also running on Stretch, btw.
>
> Regards,
>
> Dianne.
> _______________________________________________
> NOTE: If there is a disclaimer or other legal boilerplate in the above
> message, it is NULL AND VOID. You may ignore it.
>
> Visit http://www.mimedefang.org and http://www.roaringpenguin.com
> MIMEDefang mailing list MIMEDefang at lists.roaringpenguin.com
> http://lists.roaringpenguin.com/mailman/listinfo/mimedefang
>
filter attached, I am doing some other stuff in there but as I said this
filter has been in place for many years and only recently have those
errors been occurring...
Thank you,
Mark Adrian Coetser
-------------- next part --------------
# -*- 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: mimedefang-filter,v 1.7 2009/10/12 09:49:13 root Exp $
#***********************************************************************
$SALocalTestsOnly = 0;
#***********************************************************************
# 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 domain.co.za';
$AdminName = "PKF mail firewall";
#***********************************************************************
# 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 domain.co.za';
$LocalHostName = 'mailhub01';
#***********************************************************************
# 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)) {
# 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|zip|\{[^\}]+\})';
# Do not allow:
# - CLSIDs {foobarbaz}
# - bad extensions (possibly with trailing dots) at end
$re = '\.' . $bad_exts . '\.*$';
return 1 if (re_match($entity, $re));
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");
# }
# 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");
}
# This will clean up HTML if Anomy::HTMLCleaner is installed.
# NOTE: We consider Anomy::HTMLCleaner to be TOO BUGGY for
# production use. Uncomment the next lines at your peril!
#if ($Features{"HTMLCleaner"}) {
# if ($type eq "text/html") {
# return anomy_clean_html($entity);
# }
#}
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");
# }
# 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();
}
#***********************************************************************
# %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";
}
my $sendmailCF_file = '/etc/mail/sendmail.cf';
open(sendmailCF_file_OPEN, $sendmailCF_file) or die("Could not open $sendmailCF_file\n$!");
my @raw_lines = <sendmailCF_file_OPEN>;
close(sendmailCF_file_OPEN);
my @good_lines = ();
for my $line (@raw_lines) {
if ($line =~ /D\{sendmailMTACluster\}/) {
chomp($line);
@fields = split('}', $line);
$sendmailMTACluster = $fields[1];
}
}
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();
use Net::LDAP;
$ldap = Net::LDAP->new ( "localhost" ) or die "$@";
$mesg = $ldap->bind ( version => 3 ); # use for searches
#$mesg = $ldap->bind ( "$userToAuthenticate",
# password => "$passwd",
# version => 3 ); # use for changes/edits
# see your LDAP administrator for information concerning the
# user authentication setup at your site.
sub LDAPsearch {
my ($ldap,$searchString,$attrs,$base) = @_;
# if they don't pass a base... set it for them
if (!$base ) { $base = "dc=root"; }
# if they don't pass an array of attributes...
# set up something for them
if (!$attrs ) { $attrs = [ 'cn','mail' ]; }
my $result = $ldap->search ( base => "$base",
scope => "sub",
filter => "$searchString",
attrs => $attrs
);
}
sub LDAPsearch_results {
my ($searchString,$attrs) = @_;
my $result = LDAPsearch ($ldap, $searchString,$attrs);
my @entries = $result->entries;
my $entr;
foreach $entr ( @entries ) {
my $attr;
foreach $attr ( sort $entr->attributes ) {
# skip binary we can't handle
next if ( $attr =~ /;binary$/ );
return $entr->get_value ( $attr );
}
}
}
sub filter_ARCHIVE {
# rewrite and remove domain lookup loop, search on sendmailMTAClassName and if result archive
my ($archive_domain,$archive_email,$archive_user,$direction) = @_;
$ldap_search_str = "(&(sendmailMTAClassValue=$archive_domain)(sendmailMTAClassName=archive_domains)(sendmailMTACluster=$sendmailMTACluster))";
my $archive_on = LDAPsearch_results ($ldap_search_str,['sendmailMTAClassName']);
if ($archive_on) {
$searchString = "(|(mail=$archive_email)(mailRoutingAddress=$archive_email))";
my $archive_uid = LDAPsearch_results ($searchString,['uid']);
if ($archive_uid) {
$archiveaddr = $archive_uid . '@archive.' . $archive_domain;
add_recipient ($archiveaddr);
$archive_msg = "archived $LocalHostName for $archive_email";
action_add_header("X-PKFArchive",$archive_msg);
}
}
}
# save on dns lookups
#$archive_server01 = inet_ntoa(inet_aton('archive01.domain.co.za'));
#$archive_server02 = inet_ntoa(inet_aton('archive01.domain.co.za'));
$archive_server01 = "192.168.60.21";
$archive_server02 = "192.168.60.22";
if (($RelayAddr ne $archive_server01) && ($RelayAddr ne $archive_server02)) {
my $stripped_recip;
my $recip_user;
my $recip_domain;
my $recip_archive_domain;
my $recip;
foreach $recip (@Recipients) {
$stripped_recip = $recip;
$stripped_recip =~ tr/<>//d;
$stripped_recip = lc $stripped_recip;
$recip_user = $stripped_recip;
$recip_user =~ s/(^.*)\@.*/$1/;
$recip_domain = $stripped_recip;
$recip_domain =~ s/.*\@(.*$)/$1/;
if ($recip_user =~ /_at_/i) {
$recip_archive_domain = $recip_user;
$recip_archive_domain =~ s/.*\_at_(.*$)/$1/;
}
else {
$recip_archive_domain = $recip_domain;
}
#$recip_fulladdr = $recip_user . '@' . $recip_domain;
&filter_ARCHIVE ($recip_archive_domain,$stripped_recip,$recip_user,"recipient");
}
my $stripped_sender;
my $sender_user;
my $sender_domain;
$stripped_sender = $Sender;
$stripped_sender =~ tr/<>//d;
$stripped_sender = lc $stripped_sender;
$sender_user = $stripped_sender;
$sender_user =~ s/(^.*)\@.*/$1/;
$sender_domain = $stripped_sender;
$sender_domain =~ s/.*\@(.*$)/$1/;
#$sender_fulladdr = $sender_user . '@' . $sender_domain;
&filter_ARCHIVE ($sender_domain,$stripped_sender,$sender_user,"sender");
}
# 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;
More information about the MIMEDefang
mailing list