Hi,

I just wrote greylisting support for SA (to use at SMTP time with SA-Exim,
http://marc.merlins.org/linux/exim/sa.html)
(patched attached if you're interested)

I call my rule as such:
header GREYLIST_ISWHITE eval:greylisting('/var/spool/sa-exim/tuplets', "dir", 
"1800", "X-SA-Exim-Connect-IP", "X-SA-Exim-Mail-From", "X-SA-Exim-Rcpt-To")
describe GREYLIST_ISWHITE The incoming server has been whitelisted for this 
receipient
score GREYLIST_ISWHITE  -6

I would however like the following thing:
How do I run this rule close to last, and only if  5 < current score < 10 

Is there a way to do this cleanly without patching SA some more?

Thanks
Marc

PS: Here's the patch:


--- EvalTests.pm.orig   Tue Dec 30 11:48:38 2003
+++ EvalTests.pm        Sun Feb 15 11:22:22 2004
@@ -1863,6 +1863,142 @@
   return 0;
 }
 
+
+# This was originally written to implement greylisting in SA-Exim, although
+# I have tried to make it more general and allow for reuse in other MTAs
+# (although they will need to
+# 1) be running SA at SMTP time
+# 2) Provide the list of rcpt to and env from in some headers for SA to read
+# 3) Provide the IP of the connecting host )
+#
+# This rule should get a negative score so that if we've already seen the
+# greylisting tuplet before, we lower the score, which hopefully brings us from
+# a tempreject to an accept (at least that's how sa-exim does it)
+# -- Marc <[EMAIL PROTECTED]> 2004/01/19
+
+sub greylisting {
+  # db/file/dir / pointer type / how many secs to greylist after 1st connection
+  my ($self, $dirorfileordb, $method, $greylisttime,
+         $connectiphdr, $envfromhdr, $rcpttohdr) = @_;
+  my $dirorfile = shift @_;
+
+  my $connectip; 
+  my $envfrom;
+  my $rcptto;
+  my @rcptto;
+  my $iswhitelisted=0;
+
+  if (not $connectip = $self->get($connectiphdr))
+  {
+    warn "Couldn't get Connecting IP header $connectiphdr, skipping 
greylisting call\n";
+    return 0;
+  }
+  chomp($connectip);
+  # Clean up input (for security, if you use files/dirs)
+  $connectip =~ s#/#-#g;
+
+  if (not $envfrom = $self->get($envfromhdr))
+  {
+    warn "Couldn't get Envelope From header $envfromhdr, skipping greylisting 
call\n";
+    return 0;
+  }
+  chomp($envfrom);
+  # Clean up input (for security, if you use files/dirs)
+  $envfrom =~ s#/#-#g;
+
+  if (not $rcptto = $self->get($rcpttohdr))
+  {
+    warn "Couldn't get Rcpt To header $rcpttohdr, skipping greylisting call\n";
+    return 0;
+  }
+  chomp($rcptto);
+  # Clean up input (for security, if you use files/dirs)
+  $rcptto =~ s#/#-#g;
+  @rcptto = split(/, /, $rcptto);
+
+  foreach $rcptto (@rcptto)
+  {
+    my $ipdir = "$dirorfileordb/$connectip";
+    my $tupletdir = "$ipdir/$envfrom";
+    my $tuplet = "$tupletdir/$rcptto";
+  
+    # The dir method is easy to fiddle with and expire records in (with
+    # a find | rm) but it's probably more I/O extensive than a real DB
+    # and suffers from directory size problems if a specific IP is sending
+    # generating tens of thousands of tuplets. -- Marc
+    if ($method eq "dir")
+    {
+      # make directory whether it's there or not (faster than test and set)
+      mkdir $ipdir;
+      mkdir $tupletdir;
+
+      if (not -e $tuplet) 
+      {
+       # If the tuplets aren't there, that's a rule failure, we touch them
+       # and continue in case there are other ones
+       umask 0770;
+       open (TUPLET, ">$tuplet") or warn "Can't create $tuplet: $!";
+       print TUPLET time."\n";
+       print TUPLET "Status: Greylisted\n";
+       print TUPLET "Whitelisted Count: 0\n";
+       print TUPLET "Query Count: 1\n";
+       close TUPLET or warn "Can't create $tuplet: $!";;
+      }
+      else
+      {
+       my $time;
+       my $status;
+       my $whitelistcount;
+       my $querycount;
+
+       # Take into account race condition of expiring deletes and us running
+       open (TUPLET, "<$tuplet") or goto diskerror;
+       $time=<TUPLET> or goto diskerror;
+       $status=<TUPLET> or goto diskerror;
+       $whitelistcount=<TUPLET> or goto diskerror;
+       $whitelistcount=~s/.*: //;
+       $querycount=<TUPLET> or goto diskerror;
+       $querycount=~s/.*: //;
+       close (TUPLET);
+
+       $querycount++;
+       if (($time - time) > $greylisttime)
+       {
+         $status="Whitelisted";
+         $whitelistcount++;
+       }
+
+       umask 0770;
+       open (TUPLET, ">$tuplet") or warn "Can't recreate $tuplet: $!";
+       print TUPLET "$time\n";
+       print TUPLET "Status: $status\n";
+       print TUPLET "Whitelisted Count: $whitelistcount\n";
+       print TUPLET "Query Count: $querycount\n";
+       close TUPLET or warn "Can't recreate $tuplet: $!";;
+
+        # We continue processing the other receipients, to setup or
+       # update their counters
+       if ($status="Whitelisted")
+       {
+         $iswhitelisted=1;
+       }
+      }
+    }
+    elsif ($method eq "file")
+    {
+      warn "codeme\n";
+    }
+    elsif ($method eq "db")
+    {
+      warn "codeme\n";
+    }
+  }
+  
+  diskerror:
+  return $iswhitelisted;
+}
+
+
 ###########################################################################
 # BODY TESTS:
 ###########################################################################
-- 
"A mouse is a device used to point at the xterm you want to type in" - A.S.R.
Microsoft is to operating systems & security ....
                                      .... what McDonalds is to gourmet cooking
Home page: http://marc.merlins.org/   |   Finger [EMAIL PROTECTED] for PGP key

Reply via email to