Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Matts (1087)

Matts
  (email not shown publicly)

I work for MessageLabs [messagelabs.com] in Toronto, ON, Canada. I write spam filters, MTA software, high performance network software, string matching algorithms, and other cool stuff mostly in Perl and C.

Journal of Matts (1087)

Friday October 18, 2002
08:34 AM

Clamav scanner for qpsmtpd

[ #8441 ]

Yesterday evening I installed Ask's qpsmtpd because I really really hated qmail-scanner-queue.pl (bad perl4 code, and horribly designed). The same evening I got most of a clamav plugin working. Today I got it working proper (and removed hundreds of lines of code in the process - I didn't realise that clamav had its own email parser in it, so I could discard all of that).

Anyway, if you want to stop (some) viruses at your gateway, here's the code (free software, blah blah - please put this in the distro if you like it, Ask):

#!/usr/bin/perl -w
# Clam-AV plugin.
 
use File::Temp qw(tempfile);
 
sub register {
  my ($self, $qp) = @_;
  $self->register_hook("data_post", "clam_scan");
}
 
sub clam_scan {
  my ($self, $transaction) = @_;
 
  my ($temp_fh, $filename) = tempfile();
  print $temp_fh $transaction->header->as_string;
  print $temp_fh "\n";
  while (my $line = $transaction->body_getline) {
    print $temp_fh $line;
  }
  seek($temp_fh, 0, 0);
 
  # Now do the actual scanning!
  my $cmd = "/usr/local/bin/clamscan --stdout -i --max-recursion=50 --disable-summary $
filename 2>&1";
  $self->log(1, "Running: $cmd");
  my $output = `$cmd`;
 
  my $result = ($? >> 8);
  my $signal = ($? & 127);
 
  unlink($filename);
  chomp($output);
 
  $output =~ s/^.* (.*) FOUND$/$1 /mg;
 
  $self->log(1, "clamscan results: $output");
 
  if ($signal) {
    $self->log(1, "clamscan exited with signal: $signal");
    return (DECLINED);
  }
  if ($result == 1) {
    $self->log(1, "Virus(es) found");
    # return (DENY, "Virus Found: $output");
    $transaction->header->add('X-Virus-Found', 'Yes');
    $transaction->header->add('X-Virus-Details', $output);
  }
  elsif ($result) {
    $self->log(1, "ClamAV error: $result\n");
  }
  $transaction->header->add('X-Virus-Checked', 'Checked');
  return (DECLINED);
}

Uncomment the "return (DENY,..)" if you never want those nasty viruses in your inbox (though I don't know how accurate clamav is, so you may want to be careful at first).

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.

  • Great! :-) I was missing something like that. I will add it to the distribution.

    I'll add a method in the transaction object so you can just get the filename of the spool file instead of having to copy it.

      - ask
    --

    -- ask bjoern hansen [askbjoernhansen.com], !try; do();