EFA Signature

Report bugs and workarounds
Post Reply
zane93
Posts: 44
Joined: 08 Mar 2016 22:08

EFA Signature

Post by zane93 »

I'm trying to figure out how some (10%) spam emails delivered to me are getting around not having the EFA Signature attached to them. Im not sure where to start trouble shooting on this one.
Due to the volume of spam that I've been getting it seems like I have a gaping hole some where.

exch.ZZZZ.com is my exchange server
exchedge.ZZZZ.com is my EFA server

Email message properties

Code: Select all

Received: from exch.ZZZZ.com (192.168.XXX.XXX) by exch.ZZZZ.com (192.168.XXX.XXX)
 with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3 via Mailbox
 Transport; Mon, 7 May 2018 10:15:18 -0500
Received: from exch.ZZZZ.com (192.168.2.CC) by exch.ZZZZ.com (192.168.XXX.XXX)
 with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3; Mon, 7 May
 2018 10:15:18 -0500
Received: from exchedge.ZZZZ.com (192.168.XXX.XXX) by exch.ZZZZ.com
 (192.168.XXX.XXX) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3 via
 Frontend Transport; Mon, 7 May 2018 10:15:18 -0500
X-Spam-Status: No
X-OC-MailScanner-EFA-Watermark: 1526310924.32519@T+P4DNjSGCGlWujLOLtoZg
X-OC-MailScanner-EFA-From: forces.locarb.induction.phase@usaimportedsupplements.com
X-OC-MailScanner-EFA-SpamScore: sss
X-OC-MailScanner-EFA: Found to be clean
X-OC-MailScanner-EFA-ID: 0445F104CC4.A8312
X-OC-MailScanner-EFA-Information: Please contact admin@ZZZZ.com for more information
X-Greylist: from auto-whitelisted by SQLgrey-1.8.0
DMARC-Filter: OpenDMARC Filter v1.3.2 exchedge.ZZZZ.com 0445F104CC4
Authentication-Results: exchedge.ZZZZ.com; dmarc=none (p=none dis=none) header.from=usaimportedsupplements.com
Authentication-Results: exchedge.ZZZZ.com; spf=pass smtp.mailfrom=forces.locarb.induction.phase@usaimportedsupplements.com
DKIM-Filter: OpenDKIM Filter v2.11.0 exchedge.ZZZZ.com 0445F104CC4
Received: from oxygen.usaimportedsupplements.com (unknown [5.83.35.137])
	by exchedge.ZZZZ.com (Postfix) with ESMTP id 0445F104CC4
	for <nZZZZ@ZZZZ.com>; Mon,  7 May 2018 10:15:21 -0500 (CDT)
To: <nZZZZ@oZZZZ.com>
From: Forces LoCarb Induction Phase
	<forces.locarb.induction.phase@usaimportedsupplements.com>
Subject: Forces conditions that increase metabolic burn process.
MIME-Version: 1
References: Fit-ID Seg.TIrE5pcWp.VITID
Priority: Normal
Errors-To: errid.71X@oxygen.usaimportedsupplements.com
Bounce-To: bouncid.71X@oxygen.usaimportedsupplements.com
Message-ID: <716372915-TpoRo.Y8ABKO.zPA7mi71mxx5tLTpoRo.Y8ABKOzPA7mi71mxx5tL@oxygen.usaimportedsupplements.com>
Reply-To: <forces.locarb.induction.phase@usaimportedsupplements.com>
Content-Type: multipart/alternative;
	boundary="_----cJohy7WC72===_22/30-12364-h7r1XE"
Date: Mon, 7 May 2018 11:15:21 -0400
Return-Path: <>
X-MS-Exchange-Organization-Network-Message-Id: 889c3995-619a-49be-53f4-08d5b42d5819
X-MS-Exchange-Organization-AVStamp-Enterprise: 1.0
X-MS-Exchange-Organization-AuthSource: exch.ZZZZ.com
X-MS-Exchange-Organization-AuthAs: Anonymous
X-MS-Exchange-Transport-EndToEndLatency: 00:00:00.2343877
X-MS-Exchange-Processed-By-BccFoldering: 15.01.1466.003
User avatar
shawniverson
Posts: 3644
Joined: 13 Jan 2014 23:30
Location: Indianapolis, Indiana USA
Contact:

Re: EFA Signature

Post by shawniverson »

Can you post the following for an affected message?

1) The message detail (spam report) of the message (or lack thereof)
2) The relevant maillog of the same affected message
zane93
Posts: 44
Joined: 08 Mar 2016 22:08

Re: EFA Signature

Post by zane93 »

Not sure if you need more from the mail log?

Code: Select all

 9 09:19:52 exchedge MailScanner[23678]: New Batch: Scanning 1 messages, 17197 bytes
May  9 09:19:52 exchedge MailScanner[23678]: Virus and Content Scanning: Starting
May  9 09:19:52 exchedge MailScanner[23678]: <A> tag found in message 7DC151056FB.A67B0 from 
May  9 09:19:52 exchedge MailScanner[23678]: <A> tag found in message 7DC151056FB.A67B0 from 
May  9 09:19:52 exchedge MailScanner[23678]: HTML Img tag found in message 7DC151056FB.A67B0 from 
May  9 09:19:52 exchedge MailScanner[23678]: Spam Checks: Starting
May  9 09:19:52 exchedge MailScanner[23678]: Message 7DC151056FB.A67B0 had bad watermark, added 2 to spam score
May  9 09:19:52 exchedge MailScanner[23678]: MailWatch: Whitelist refresh time reached
May  9 09:19:52 exchedge MailScanner[23678]: MailWatch: Starting up MailWatch SQL Whitelist
May  9 09:19:52 exchedge MailScanner[23678]: MailWatch: Read 20 whitelist entries
May  9 09:19:52 exchedge MailScanner[23678]: MailWatch: Blacklist refresh time reached
May  9 09:19:52 exchedge MailScanner[23678]: MailWatch: Starting up MailWatch SQL Blacklist
May  9 09:19:52 exchedge MailScanner[23678]: MailWatch: Read 0 blacklist entries
May  9 09:19:54 exchedge MailScanner[23678]: Requeue: 7DC151056FB.A67B0 to 81B03105913
May  9 09:19:54 exchedge postfix/qmgr[2249]: 81B03105913: from=<>, size=16066, nrcpt=1 (queue active)
May  9 09:19:54 exchedge MailScanner[23678]: Uninfected: Delivered 1 messages
May  9 09:19:54 exchedge MailScanner[23678]: Deleted 1 messages from processing-database
May  9 09:19:54 exchedge MailScanner[23678]: MailWatch: Logging message 7DC151056FB.A67B0 to SQL
May  9 09:19:54 exchedge MailScanner[30336]: MailWatch: 7DC151056FB.A67B0: Logged to MailWatch SQL
May  9 09:20:23 exchedge postfix/smtpd[31252]: connect from cal.haohuajiancai.com[23.95.101.131]
May  9 09:20:23 exchedge sqlgrey: grey: reconnect ok: 23.95.101(23.95.101.131), costa.rican.beaches@haohuajiancai.com -> MYEMAIL@YYYY.com (00:05:37)
May  9 09:20:23 exchedge sqlgrey: grey: from awl: 23.95.101, costa.rican.beaches@haohuajiancai.com added
May  9 09:20:23 exchedge postfix/smtpd[31252]: 2DE7E1056FB: client=cal.haohuajiancai.com[23.95.101.131]
May  9 09:20:23 exchedge postfix/cleanup[31501]: 2DE7E1056FB: hold: header Received: from cal.haohuajiancai.com (cal.haohuajiancai.com [23.95.101.131])??by exchedge.YYYY.com (Postfix) with ESMTP id 2DE7E1056FB??for <MYEMAIL@YYYY.com>; Wed,  9 May 2018 09:20:23 -0 from cal.haohuajiancai.com[23.95.101.131]; from=<costa.rican.beaches@haohuajiancai.com> to=<MYEMAIL@YYYY.com> proto=ESMTP helo=<cal.haohuajiancai.com>
May  9 09:20:23 exchedge postfix/cleanup[31501]: 2DE7E1056FB: message-id=<LFO8osPr484216096628772542582.00099-URSiYx-963138570851212743833QHqKfiRh5yODllTXc0A1998E8sdeUitOqOLXJBz@cal.haohuajiancai.com>
May  9 09:20:23 exchedge opendkim[1239]: 2DE7E1056FB: cal.haohuajiancai.com [23.95.101.131] not internal
May  9 09:20:23 exchedge opendkim[1239]: 2DE7E1056FB: not authenticated
May  9 09:20:23 exchedge opendkim[1239]: 2DE7E1056FB: no signature data
May  9 09:20:23 exchedge opendmarc[2482]: 2DE7E1056FB: SPF(mailfrom): costa.rican.beaches@haohuajiancai.com pass
May  9 09:20:23 exchedge opendmarc[2482]: 2DE7E1056FB: haohuajiancai.com none
May  9 09:20:23 exchedge postfix/smtpd[31252]: disconnect from cal.haohuajiancai.com[23.95.101.131] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5

Code: Select all

Received on:	09/05/18 09:20:25
Received by:	exchedge.YYYY.com
Received from:	
23.95.101.131	[Add to Whitelist | Add to Blacklist]
Received Via:	
IP Address	Hostname	Country	RBL	Spam	Virus	All
23.95.101.131	cal.haohuajiancai.com	United States	[  ]	[  ]	[  ]	[  ]
ID:	2DE7E1056FB.A93A1
Message Headers:	X-Greylist: delayed 00:05:37 by SQLgrey-1.8.0
DMARC-Filter: OpenDMARC Filter v1.3.2 exchedge.YYYY.com 2DE7E1056FB
Authentication-Results: exchedge.YYYY.com; dmarc=none (p=none dis=none) header.from=haohuajiancai.com
Authentication-Results: exchedge.YYYY.com; spf=pass smtp.mailfrom=costa.rican.beaches@haohuajiancai.com
DKIM-Filter: OpenDKIM Filter v2.11.0 exchedge.YYYY.com 2DE7E1056FB
Received: from cal.haohuajiancai.com (cal.haohuajiancai.com [23.95.101.131])
     by exchedge.YYYY.com (Postfix) with ESMTP id 2DE7E1056FB
     for <MYEMAIL@YYYY.com>; Wed, 9 May 2018 09:20:23 -0500 (CDT)
To: MYEMAIL@YYYY.com
From: Costa Rican Beaches <costa.rican.beaches@haohuajiancai.com>
MIME-Version: 1
Subject: Costa Rica- dance, dine, beaches, your hard earned goes so far here.
References: ref6798003
Reply-To: costa.rican.beaches@haohuajiancai.com
Message-ID: <LFO8osPr484216096628772542582.00099-URSiYx-963138570851212743833QHqKfiRh5yODllTXc0A1998E8sdeUitOqOLXJBz@cal.haohuajiancai.com>
Content-Type: multipart/alternative; boundary="_000---11111.33333-72f5e4uOHipe__24337119-abg9myWKhO"
Date: Wed, 9 May 2018 10:20:23 -0400
From:	
costa.rican.beaches@haohuajiancai.com	[Add to Whitelist | Add to Blacklist]
To:	MYEMAIL@YYYY.com
Subject:	Costa Rica- dance, dine, beaches, your hard earned goes so far here.
Size:	7.44kB
Anti-Virus/Dangerous Content Protection
Virus:	 N 
Blocked File:	 N 
Other Infection:	 N 
SpamAssassin
Spam:	 N   Action(s): store, deliver, header, "X-Spam-Status:No", custom(nonspam)
High Score Spam:	 N 
SpamAssassin Spam:	 N 
Listed in RBL:	 N 
SPAM Whitelisted:	 N 
SPAM Blacklisted:	 N 
SpamAssassin Autolearn:	 N 
SpamAssassin Score:	3.62
Spam Report:	
Score	Matching Rule	Description
0.80	BAYES_50	Bayes spam probability is 40 to 60%
0.00	HTML_MESSAGE	HTML included in message
1.89	RAZOR2_CF_RANGE_51_100	Razor2 gives confidence level above 50%
0.92	RAZOR2_CHECK	Listed in Razor2 (http://razor.sf.net/)
0.00	RCVD_IN_DNSWL_BLOCKED	ADMINISTRATOR NOTICE: The query to DNSWL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists\#dnsbl-block for more information.
-0.00	SPF_HELO_PASS	SPF: HELO matches SPF record
-0.00	SPF_PASS	SPF: sender matches SPF record
0.01	T_REMOTE_IMAGE	Message contains an external image
0.00	URIBL_BLOCKED	ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists\#dnsbl-block for more information.
Relay Information:	
Date/Time	Relayed by	Relayed to	Delay	Status
09/05/18 09:20:25	exchedge	192.168.2.210	00:00:02	sent (250 2.6.0 [InternalId=97096325660693, Hostname=exch.YYYY.com] 8317 bytes in 0.113, 71.537 KB/sec Queued mail for delivery)
User avatar
shawniverson
Posts: 3644
Joined: 13 Jan 2014 23:30
Location: Indianapolis, Indiana USA
Contact:

Re: EFA Signature

Post by shawniverson »

On your exchange, can you view the source of this message and confirm that there is no signature line?

I'm wondering if the preceding message itself may be mangling the signature line...
zane93
Posts: 44
Joined: 08 Mar 2016 22:08

Re: EFA Signature

Post by zane93 »

I dont know of a way to look at the message in Exchange 2016 if its not in the queue but Im sure there is a way Ill look into it but it does not seem like its being augmented their. Something Ive noticed is the all spam that get through comes in pairs usually 4 to 8 at a time. The ones that do not have a signature also come in pairs. If I view the message in EFA Console the message do not have a signature is that standard?(bottom)

Code: Select all

09/05/18 09:20:45	costa.rican.beaches@candacecatherine.com	nconder@opulentcomputing.com	Costa Rica- dance, dine, beaches, your hard earned goes so far here.	7.59kB	3.62	Clean
09/05/18 09:20:25	costa.rican.beaches@haohuajiancai.com	nconder@opulentcomputing.com	Costa Rica- dance, dine, beaches, your hard earned goes so far here.	7.44kB	3.62	Clean

Code: Select all

me beat up this woman, got it?" he and the ref from takeover's tag match
can just sit on the couch and watch the show next time lol i think it was
the same ref! i feel like hunter basically changed the rules and informed
him of that when he set drake in the corner so he and ronda could go at it.
"bud, it's a tornado intergender match now. just count the pin." announcers

[perfectly costa rica]
http://www.haohuajiancai.com/learning/nd/haoD2THHsZd5gDdir1fJDNyr1%2FaYvA8ual8FY0WxAw9Vcfl%2B2u5yliXWaa%2BXfp3jMfhNJ0HiJ2eLAAT27InJp06hw%3D%3Dhua

Caribbean nights on red-sun beaches. Beautiful relaxing vacations sitting
beneath a beach umbrella, watching the waves roll in...

I WANT TO GO 
(http://www.haohuajiancai.com/learning/nd/haoD2THHsZd5gDdir1fJDNyr1%2FaYvA8ual8FY0WxAw9Vcfl%2B2u5yliXWaa%2BXfp3jMfhNJ0HiJ2eLAAT27InJp06hw%3D%3Dhua)

http://med.haohuajiancai.com/more/2haoD2THHsZd5gDdir1fJDNyr1%2FaYvA8ual8FY0WxAw9Vcfl%2B2u5yliXWaa%2BXfp3jMfhNJ0HiJ2eLAAT27InJp06hw%3D%3Dhuabl/
EFA Console Message
EFA Console Message
2018-05-09_17-36-21.jpg (456.84 KiB) Viewed 8920 times
henk
Posts: 517
Joined: 14 Dec 2015 22:16
Location: Netherlands
Contact:

Re: EFA Signature

Post by henk »

Hi Zane93,
Spam: N Action(s): store, deliver, header, "X-Spam-Status:No", custom(nonspam)
the custom(nonspam) action will overide the Sign Clean Messages and add a -conditional- Signature .
The culprit may be in this script.

Code: Select all

 /etc/MailScanner/custom/CustomAction.pm 

Next to this issue, did you notice these warnings, a clear indication of dns issues. Solving this will should be the nr 1 priority, I think.

Code: Select all

0.00	RCVD_IN_DNSWL_BLOCKED	ADMINISTRATOR NOTICE: The query to DNSWL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists\#dnsbl-block for more information.
0.00	URIBL_BLOCKED	ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists\#dnsbl-block for more information.
“We are stuck with technology when what we really want is just stuff that works.” -Douglas Adams
zane93
Posts: 44
Joined: 08 Mar 2016 22:08

Re: EFA Signature

Post by zane93 »

I have enabled "dns recursion" on efa and I have removed google dns servers from my dns servers will that help resolve my dns issues?

I subscribe to MalwarePatrol could that be causing an issue here with the custom script because I've never modified this file CustomAction.pm that I know of?

Code: Select all

# CustomAction.pm
# Version 20140309
# +--------------------------------------------------------------------+
# Copyright (C) 2012~2015 http://www.efa-project.org
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# +--------------------------------------------------------------------+

package MailScanner::CustomConfig;

use strict 'vars';
use strict 'refs';
no  strict 'subs'; # Allow bare words for parameter %'s

use vars qw($VERSION);

# The package version, both in 1.23 style *and* usable by MakeMaker:
$VERSION = substr q$Revision: 1.0 $, 10;

use DBI;

#
# CustomAction for EFA Token Generation
#
sub CustomAction {
 my($message,$yes_or_no,$param) = @_;
 if ($param =~ /^spam$/ ) {
   return EFASpamNotify($message);
 }
 if ($param =~ /^nonspam$/ ) {
   return EFANonSpam($message);
 }
}

#
# EFA Non Spam Modification Token Generation,
#
sub EFANonSpam {
  my($message) = @_;
  my($token);
  my($file);
  my($spamwhitelisted);

  # Generate Token/Sign unless message is originates from localhost or is inbound and whitelisted
  my($clientip) = $message->{clientip};

  if ($clientip =~ /^127/) {
    return $message;
  } else {
    $message->MailScanner::Message::IsAReply();
	# Is inbound or outbound signature being applied?
	$file = MailScanner::Config::Value("inlinetextsig", $message);
	$spamwhitelisted = $message->{spamwhitelisted};
    if($message->{isreply}) {
      # Message is a reply, do not sign
      return $message;
    } elsif ($file =~ /inline.sig.in.txt/ && $spamwhitelisted eq "1") {
	  # Message is inbound and whitelisted, do not sign
	  return $message;
    } else {
      $token = EFACreateToken();

      $message->{token} = $token;

      return SignNonSpam($message);
    }
  }
}

#
# EFA Token Creation
#
sub EFACreateToken {
  my($dbh, $sth, $sql);
  my($db_name) = 'efa';
  my($db_host) = 'localhost';
  my($db_user) = 'efa';
  my($fh);
  my($pw_config) = '/etc/EFA-Config';
  open($fh, "<", $pw_config);
  if(!$fh) {
    MailScanner::Log::WarnLog("Unable to open %s to retrieve password", $pw_config);
	return;
  }
  my($db_pass) = grep(/^EFASQLPWD/,<$fh>);
  $db_pass =~ s/EFASQLPWD://;
  $db_pass =~ s/\n//;
  close($fh);
  # Connect to the database
  $dbh = DBI->connect("DBI:mysql:database=$db_name;host=$db_host",
                      $db_user, $db_pass,
                      {PrintError => 0});

  # Check if connection was successfull - if it isn't
  # then generate a warning and continue processing.
  if (!$dbh) {
   MailScanner::Log::WarnLog("Unable to initialise database connection: %s", $DBI::errstr);
   return;
  }

  # Generate a new token
  my($token) = randomtoken();

  $sql = "INSERT INTO tokens (token, datestamp) VALUES ('$token', NOW())";
  $sth = $dbh->prepare($sql);
  $sth->execute;

  # Close connections
  $sth->finish();
  $dbh->disconnect();

  # Return $token
  return $token;
}

#
#  EFA Spam Token Generation and Notification
#
sub EFASpamNotify {
  my($message) = @_;
  my($token);

  $token = EFACreateToken();
  #if (!$token) { return; }

  $message->{token} = $token;

  # Notify user
  HandleSpamNotify($message);

  return 0;
}

# +---------------------------------------------------+
# # Function to create a pseudorandom 32 char token
# # +---------------------------------------------------+
sub randomtoken {
   my($token) = `date | md5sum | tr -cd '[:alnum:]'`;
   return $token;
}
# +---------------------------------------------------+

# Code borrowed from Messages.pm and modified for use with EFA
#
# We want to send a message to the recipient saying that their spam
# mail has not been delivered.
# Send a message to the recipients which has the local postmaster as
# the sender.
sub HandleSpamNotify {
  my($message) = @_;
  my($from,$to,$subject,$date,$spamreport,$hostname,$day,$month,$year);
  my($emailmsg, $line, $messagefh, $filename, $localpostmaster, $id);
  my($postmastername);
  my($token);

  $from = $message->{from};

  # Don't ever send a message to "" or "<>"
  return if $from eq "" || $from eq "<>";

  # Do we want to send the sender a warning at all?
  # If nosenderprecedence is set to non-blank and contains this
  # message precedence header, then just return.
  my(@preclist, $prec, $precedence, $header);
  @preclist = split(" ",
                  lc(MailScanner::Config::Value('nosenderprecedence', $message)));
  $precedence = "";
  foreach $header (@{$message->{headers}}) {
    $precedence = lc($1) if $header =~ /^precedence:\s+(\S+)/i;
  }
  if (@preclist && $precedence ne "") {
    foreach $prec (@preclist) {
      if ($precedence eq $prec) {
        MailScanner::Log::InfoLog("Skipping sender of precedence %s",
                                  $precedence);
        return;
      }
    }
  }

  # Setup other variables they can use in the message template
  $id = $message->{id};
  $localpostmaster = MailScanner::Config::Value('localpostmaster', $message);
  $postmastername  = MailScanner::Config::LanguageValue($message, 'mailscanner');
  $hostname = MailScanner::Config::Value('hostname', $message);
  $subject = $message->{subject};
  $date = $message->{datestring}; # scalar localtime;
  $spamreport = $message->{spamreport};
  $token = $message->{token};
  # And let them put the date number in there too
  #($day, $month, $year) = (localtime)[3,4,5];
  #$month++;
  #$year += 1900;
  #my $datenumber = sprintf("%04d%02d%02d", $year, $month, $day);
  my $datenumber = $message->{datenumber};


  my($to, %tolist);
  foreach $to (@{$message->{to}}) {
    $tolist{$to} = 1;
  }
  $to = join(', ', sort keys %tolist);

  # Delete everything in brackets after the SA report, if it exists
  $spamreport =~ s/(spamassassin)[^(]*\([^)]*\)/$1/i;

  # Work out which of the 3 spam reports to send them.
  $filename = MailScanner::Config::Value('recipientspamreport', $message);
  MailScanner::Log::NoticeLog("Spam Actions: Notify %s", $to)
    if MailScanner::Config::Value('logspam');

  $messagefh = new FileHandle;
  $messagefh->open($filename)
    or MailScanner::Log::WarnLog("Cannot open message file %s, %s",
                                 $filename, $!);
  $emailmsg = "";
  while(<$messagefh>) {
    chomp;
    s#"#\\"#g;
    s#@#\\@#g;
    # Boring untainting again...
    /(.*)/;
    $line = eval "\"$1\"";
    $emailmsg .= MailScanner::Config::DoPercentVars($line) . "\n";
  }
  $messagefh->close();

  # Send the message to the spam sender, but ensure the envelope
  # sender address is "<>" so that it can't be bounced.
  $global::MS->{mta}->SendMessageString($message, $emailmsg, $localpostmaster)
    or MailScanner::Log::WarnLog("Could not send sender spam notify, %s", $!);
}

#
# Code borrowed from Message.pm modified for use with EFA
#
sub SignNonSpam {
  my($message) = @_;
  my($from);
  return if $message->{infected}; # Double-check!

  $from = $message->{from};

  # Don't ever send a message to "" or "<>"
  return if $from eq "" || $from eq "<>";

  my($entity, $scannerheader, $clientip);

  # Use the presence of an X-MailScanner: header to decide if the
  # message will have already been signed by another MailScanner server.
  $scannerheader = MailScanner::Config::Value('mailheader', $message);
  $scannerheader =~ tr/://d;

  # EFA
  # Change Signing Behavior do not sign messages from localhost
  $clientip = $message->{clientip};
  if ($clientip =~ /^127/) { return $message; }

  # Want to sign the bottom of the highest-level MIME entity
  $entity = $message->{entity};
  if (MailScanner::Config::Value('signalreadyscanned', $message) ||
      (defined($entity) && !$entity->head->count($scannerheader))) {
      AppendSignCleanEntity($message, $entity, 0);
    if ($entity && $entity->head) {
      $entity->head->add('MIME-Version', '1.0')
        unless $entity->head->get('mime-version');
    }
    $message->{bodymodified} = 1;
  }
  return $message;
}
#
# Code borrowed from Messages.pm modified for use with EFA
# Code is identical execpt message is passed as parameter instead of
# being called from method
#
sub AppendSignCleanEntity {
  my($message, $top, $parent) = @_;

  my($MimeType, $signature, @signature);

  return unless $top;

  #print STDERR "In AppendSignCleanEntity, signing $top\n";

  # If multipart, try to sign our first part
  if ($top->is_multipart) {
    my $sigcounter = 0;
    # JKF Signed and encrypted multiparts must not be touched.
    # JKF Instead put the sig in the epilogue. Breaks the RFC
    # JKF but in a harmless way.
    if ($top->effective_type =~ /multipart\/(signed|encrypted)/i) {
      # Read the sig and put it in the epilogue, which may be ignored
      $signature = ReadVirusWarning($message,'inlinetextsig');
      @signature = map { "$_\n" } split(/\n/, $signature);
      unshift @signature, "\n";
      $top->epilogue(\@signature);
      return 1;
    }
    # If the ASCE(0) returned -1 then we found something we could sign but
    # chose not to, so set $sigcounter so we won't try to sign anything else.
    my $result0 = AppendSignCleanEntity($message, $top->parts(0), $top);
    if ($result0 >= 0) {
      $sigcounter += $result0;
    } else {
      $sigcounter = -1;
    }
    # If the ASCE(1) returned -1 then we found something we could sign but
    # chose not to, so set $sigcounter so we won't try to sign anything else.
    if ($top->head and $top->effective_type =~ /multipart\/alternative/i) {
      my $result1 = AppendSignCleanEntity($message, $top->parts(1), $top);
      if ($result1 >= 0) {
        $sigcounter += $result1;
      } else {
        $sigcounter = -1;
      }
    }

    if ($sigcounter == 0) {
      # If we haven't signed anything by now, it must be a multipart
      # message containing only things we can't sign. So add a text/plain
      # section on the front and sign that.
      my $text = ReadVirusWarning($message, 'inlinetextsig') . "\n\n";
      my $newpart = build MIME::Entity
                          Type => 'text/plain',
                          Charset =>
                    MailScanner::Config::Value('attachmentcharset', $message),
                          Disposition => 'inline',
                          Data => $text,
                          Encoding => 'quoted-printable',
                          Top => 0;
      $top->add_part($newpart, 0);
      $sigcounter = 1;
    }
    return $sigcounter;
  }

  $MimeType = $top->head->mime_type if $top->head;
  return 0 unless $MimeType =~ m{text/(html|plain)}i; # Won't sign non-text message.
  # Won't sign attachments.
  return 0 if $top->head->mime_attr('content-disposition') =~ /attachment/i;
  # Won't sign HTML parts when we already have a sig and don't allow duplicates
  # Or we are a reply and we don't sign replies.
  # We return -1 as a special token indicating that there was something we
  # could sign but chose not to. If I pick up a -1 when called then don't
  # try to sign anything else.
  return -1 if ($message->{sigimagepresent} &&
                $MimeType =~ /text\/html/i &&
                MailScanner::Config::Value('allowmultsigs', $message) !~ /1/) ||
               ($message->{isreply} &&
                MailScanner::Config::Value('isareply', $message));

  # Get body data as array of newline-terminated lines
  $top->bodyhandle or return undef;
  my @body = $top->bodyhandle->as_lines;

  # Output original data back into body, followed by message
  my($line, $io, $FoundHTMLEnd, $FoundBodyEnd, $FoundSigMark, $html);
  $FoundHTMLEnd = 0; # If there is no </html> tag, still append the signature
  $FoundBodyEnd = 0; # If there is no </body> tag, still append the signature
  $FoundSigMark = 0; # Try to replace _SIGNATURE_ with the sig if it's there
  $html = 0;
  $io = $top->open("w");
  if ($MimeType =~ /text\/html/i) {
    $signature = ReadVirusWarning($message, 'inlinehtmlsig');
    foreach $line (@body) {
      # Try to insert the signature where they want it.
      $FoundSigMark = 1 if $line =~ s/_SIGNATURE_/$signature/;
      $FoundBodyEnd = 1 if !$FoundSigMark && $line =~ s/\<\/body\>/$signature$&/i;
      $FoundHTMLEnd = 1 if !$FoundSigMark && !$FoundBodyEnd && $line =~ s/\<\/x?html\>/$signature$&/i;
      $io->print($line);
    }
    $io->print($signature . "\n")
      unless $FoundBodyEnd || $FoundHTMLEnd || $FoundSigMark;
    (($body[-1]||'') =~ /\n\Z/) or $io->print("\n"); # Ensure final newline
    $html = 1;
  } else {
    $signature = ReadVirusWarning($message, 'inlinetextsig');
    foreach $line (@body) {
      # Replace _SIGNATURE_ with the inline sig, if it's present.
      $FoundSigMark = 1 if $line =~ s/_SIGNATURE_/$signature/;
      $io->print($line); # Original body data
    }
    # Else just tack the sig on the end.
    $io->print("\n$signature\n") unless $FoundSigMark;
  }
  $io->close;

  # Add Image Attachment from Mail Scanner, unless there already is one
  if (MailScanner::Config::Value('attachimage', $message) =~ /1/ && !$message->{sigimagepresent}) {
    #print STDERR "Adding image signature\n";
    my $attach = MailScanner::Config::Value('attachimagetohtmlonly', $message);
    if (($html && $attach =~ /1/) || $attach =~ /0/) {
      my $filename = MailScanner::Config::Value('attachimagename', $message);
      my $ext = 'unknown';
      $ext = $1 if $filename =~ /\.([a-z]{3,4})$/;
      $ext = 'jpeg' if $ext =~ /jpg/i;
      my $internalname =  MailScanner::Config::Value('attachimageinternalname', $message);
      if (length($filename) && -f $filename) {
        my $newentity = MIME::Entity->build(Path => $filename,
                                            Top => 0,
                                            Type => "image/$ext",
                                            Encoding => "base64",
                                            Filename => $internalname,
                                            Disposition => "inline",
                                            'Content-Id:' => '<' . $internalname . '>');
        if ($parent && $parent->effective_type =~ /multipart\/related/i) {
          # It's already been signed once, so don't nest the MIME structure more
          $parent->add_part($newentity);
        } else {
          # It's a first-time sig, so next it into a multipart/related
          $top->make_multipart('related');
          $top->add_part($newentity);
        }
      }
    }
  }

  # We signed something
  return $message;
}

# Code borrowed from Messages.pm modified for use with EFA
# Modified to add token to signature line
#
# Read the appropriate warning message to sign the top of cleaned messages.
# Passed in the name of the config variable that points to the filename.
# This is also used to read the inline signature added to the bottom of
# clean messages.
# Substitutions allowed in the message are
#     $viruswarningfilename -- by default VirusWarning.txt
#     $from
#     $subject
# and $filename -- comma-separated list of infected attachments
sub ReadVirusWarning {
  my($message, $option) = @_;

  my $file = MailScanner::Config::Value($option, $message);
  my $viruswarningname = MailScanner::Config::Value('attachmentwarningfilename',
                                                    $message);
  my($line);

  #print STDERR "Reading virus warning message from $filename\n";
  my $fh = new FileHandle;
  $fh->open($file)
    or (MailScanner::Log::WarnLog("Could not open inline file %s, %s",
                                  $file, $!),
        return undef);

  # Work out the list of all the infected attachments, including
  # reports applying to the whole message
  my($typedattach, $attach, $text, %infected, $filename, $from, $subject, $id, $token);
  while (($typedattach, $text) = each %{$message->{allreports}}) {
    # It affects the entire message if the entity of this file matches
    # the entity of the entire message.
    $attach = substr($typedattach,1);
    my $entity = $message->{file2entity}{"$attach"};
    #if ($attach eq "") {
    if ($message->{entity} eq $entity) {
      $infected{MailScanner::Config::LanguageValue($message, "theentiremessage")}
        = 1;
    } else {
      $infected{"$attach"} = 1;
    }
  }
  # And don't forget the external bodies which are just entity reports
  while (($typedattach, $text) = each %{$message->{entityreports}}) {
    $infected{MailScanner::Config::LanguageValue($message, 'notnamed')} = 1;
  }
  $attach = substr($typedattach,1);
  $filename = join(', ', keys %infected);
  $id = $message->{id};
  $from = $message->{from};
  $subject = $message->{subject};
  my($token) = $message->{token};
  my($hostname) = MailScanner::Config::Value('hostname', $message);

  my $result = "";
  while (<$fh>) {
    chomp;
    s#"#\\"#g;
    s#@#\\@#g;
    # Boring untainting again...
    /(.*)/;
    $line = eval "\"$1\"";
    $result .= MailScanner::Config::DoPercentVars($line) . "\n";
  }
  $fh->close();
  $result;
}

1;
henk
Posts: 517
Joined: 14 Dec 2015 22:16
Location: Netherlands
Contact:

Re: EFA Signature

Post by henk »

About dns: take a look at: viewtopic.php?f=5&t=934 and viewtopic.php?f=14&t=3032

Fixing your dns issue will improve spam cathing a lot.

Subscribing to MalwarePatrol will not cause the signing issue. The CustomAction.pm is created by efa and should add the signature.
As it works fine, there must be a condition that will prevent the signing somehow.
I guess you should first answer shawns question:
On your exchange, can you view the source of this message and confirm that there is no signature line?
before he will spend time on this issue, I think.
“We are stuck with technology when what we really want is just stuff that works.” -Douglas Adams
zane93
Posts: 44
Joined: 08 Mar 2016 22:08

Re: EFA Signature

Post by zane93 »

It seems like fixing my DNS had fixed the issue so far. I'm not sure how DNS issues can cause the EFA signature not to be written to some message yet either. I will continue to investigate and report back if I come across anything.
Post Reply