One of a number of similar changes I've made lately, this adds a maximum
size constraint on clamav.  This eliminates the situation where clamav
doesn't finish its scan before the SMTP timeout alarm goes off, which
(a) wastes CPU time and blocks large email, and (b) leaves big files in
the tmpdir.  Viruses are seldom if ever found in large files these days,
so scanning them is largely a waste of time anyway.

On this subject, given the number of plugins that write the mail out to
a tempfile before passing it to something external (clamav, spamc, etc),
I'd like to suggest an addition to Qpsmtpd::Transaction.  It'd be good
to have a call to (a) guarantee that the mail is on disk, and (b) return
a filename for it (with the expectation that it won't be altered).  Then
we could skip out on repetitive tmpfile generation and cleanup in
various plugins (in which it's lots simpler to snag stdin from a file
than to deal with getting stdin+stdout pipes set up.)

(this is a merge from my own copy of the clamav plugin, since my
production qpsmtpd is a ways behind CVS; it looks sane but I haven't
tested the merged copy)

-- 
Devin  \ aqua(at)devin.com, 1024D/E9ABFCD2;  http://www.devin.com
Carraway \ IRC: Requiem  GCS/CC/L s-:--- !a !tv C++++$ ULB+++$ O+@ P L+++
Index: clamav
===================================================================
RCS file: /cvs/public/qpsmtpd/plugins/clamav,v
retrieving revision 1.3
diff -u -r1.3 clamav
--- clamav      5 Mar 2004 12:46:24 -0000       1.3
+++ clamav      15 Jun 2004 15:54:54 -0000
@@ -7,6 +7,9 @@
   my ($self, $qp, @args) = @_;
   $self->register_hook("data_post", "clam_scan");
 
+  # default scan size limit of 512k
+  $self->{_max_size} = 1024 * 512;
+
   if (@args > 0) {
     # Untaint scanner location
     if ($args[0] =~ /^(\/[\/\-\_\.a-z0-9A-Z]*)$/) {
@@ -15,16 +18,36 @@
       $self->log(LOGERROR, "FATAL ERROR: Unexpected characters in clamav argument 1");
       exit 3;
     }
-    $self->log(LOGWARN, "WARNING: Ignoring additional arguments.") if (@args > 1);
+    if (@args > 2) {
+      if ($args[0] =~ /^(\d+)$/) {
+        $self->{_max_size} =  $1;
+      } else {
+        $self->log(LOGERROR, "FATAL ERROR: Unexpected characters in clamav argument 
2");
+        exit 3;
+      }
+    }
+    $self->log(LOGWARN, "WARNING: Ignoring additional arguments.") if (@args > 2);
   } else {
     $self->{_clamscan_loc} = "/usr/local/bin/clamscan";
   }
+
 }
  
 sub clam_scan {
   my ($self, $transaction) = @_;
  
-  my ($temp_fh, $filename) = tempfile();
+  if ($transaction->body_size > $self->{_max_size}) {
+       $self->log(2, 'Mail too large to scan ('.
+               $transaction->body_size . " vs $self->{_max_size})" );
+       return (DECLINED);
+  }
+
+  my $spool_dir = $self->qp->config('spool_dir') ?
+          $self->qp->config('spool_dir')
+         : Qpsmtpd::Utils::tildeexp('~/tmp/');
+
+  my ($temp_fh, $filename) = tempfile("qpsmtpd.clamav.XXXXXX",
+         DIR => $spool_dir);
   print $temp_fh $transaction->header->as_string;
   print $temp_fh "\n";
   $transaction->body_resetpos;

Attachment: signature.asc
Description: Digital signature

Reply via email to