Hari Kurup wrote at 9:32 am (+0300) on Thu 28 Apr 2005: >Thanks Ben. It works but as you mentioned, my CPU utilisation is >always not less than 80%. >I do not require to check for authenticated sessions as I don't do any >authenticated smtp so could you kindly send me the earlier version of >your filter that does not have this?
Certainly -- attached. I suspect that the high load situation is caused by the header-parsing bit looping indefinitely on an EOF condition in some circumstances; I suspect it can be solved by changing the while(1) to while(eof()) on line 63 but I have not verified this yet. In the mean time here is the simpler version with the auth check rolled back which seems to work reliably. -ben -- Ben Kennedy, chief magician zygoat creative technical services 613-228-3392 | 1-866-466-4628 http://www.zygoat.ca
# ClamAV and etc filter for Courier perlfitler. See the perlfilter-example that # comes with Courier for the comments. # Installed by BRK on 07 July 2004 from http://karmak.org/2004/courier-clamav/ # BRK also altered return status from 500 to 577 which seems more consistent with rfc1893. # 05 Nov 2004: BRK modified to first scan the incoming message and reject if # there is no From: header provided. Seems there are spammy things getting through # with no header, so by virtue of maildrop etc. it ends up misleadingly with the # recipient user's own address. # 13 Dec 2004: BRK modified again to also call spamc and check for an egregious spam score # following a successful virus check. This is an effort to cull out the most obvious # crap before it even gets to the maildrop process. # 20 Apr 2005: BRK modified; we now check the first Received: header to see whether the # message came from an authenticated session. If so, we bypass the virus and spam checks. # 27 Apr - rolled back; somehow this is getting stuck and eating lots of cpu. use IO::File; my $filedesc=shift @ARGV; my $socket=new IO::File "+<&$filedesc"; die "$!" unless defined $socket; my $line; my $first=1; my $errmsg="200 Ok"; while (defined ($line=<$socket>)) { my $msg; chomp $line; last unless $line; if ($first) { $msg=filterdata($line); } else { $msg=filtercontrol($line); } $first=0; $errmsg=$msg if $msg; } $errmsg .= "\n" unless $errmsg =~ /\n$/; print $socket $errmsg; $socket->close; sub filterdata { my $filename=shift; # BRK: First scan the input file to ensure there is a From: header. my $goodfrom = 0; # whether we have found presence of a From: header open(FILE, "<${filename}"); my $nextline = <FILE>; # fetch first line while(<FILE>) { my $p = $_; # If this is a From header, make note of its presence. if ($p =~ /^From\: /) { $goodfrom = 1; } # If this is the end of the headers, or if we've found the From:, # no need to continue parsing. if ($p eq '' || ($goodfrom)) { last; } } close FILE; if (!$goodfrom) # If no From: header existed, barf up with the error. { return '550 Please provide a From: header in the message.'; } # We passed; now see if it smells like fish. # diag: dump env. #open(E, '>/tmp/msg.env'); #my $key; #foreach $key (sort(keys %ENV)) # { print E, $key . ' = ' . $ENV{$key} . "\n"; } #close E; open(SPAMOUT, "cat ${filename} | spamc -c -U /var/run/spamd.sock |"); my $result = <SPAMOUT>; close(SPAMOUT); # Fetch result which will be "score/threshold", e.g. "6.9/4.0". $result =~ m/^([0-9.]+)/; # Extract the score. $result = $1; # Fail if the score is reasonably large. if ($result > 4.9) { return "571 Identified spam ($result). Contact [EMAIL PROTECTED] if this is in error."; } # Now, carry on with the original CLAMAV scanning. open(CLAMOUT, "cat ${filename} | clamdscan --stdout - |"); my $result = <CLAMOUT>; close(CLAMOUT); if ( $result =~ m/ FOUND$/ ) { $result =~ s/.*stream: (.*) FOUND/$1/; chomp $result; # strip trailing newline (?) return "577 Virus detected (${result})."; } # Otherwise all looks good, so return usual. return ""; } sub filtercontrol { my $filename=shift; return ""; }
