Subversion Repositories

?revision_form?Rev ?revision_input??revision_submit??revision_endform?

Rev 76 | Blame | Compare with Previous | Last modification | View Log | RSS feed

Description: Add IPv6 support to the Greylisting SpamAssassin plugin.
 The greylistfourthbyte option, for IPv6 addresses, means that all
 addresses in the same /64 get whitelisted as a group.
Bug: https://bugs.debian.org/508161

--- a/Greylisting.pm
+++ b/Greylisting.pm
@@ -21,6 +21,8 @@ package Greylisting;
 
 use strict;
 use Mail::SpamAssassin::Plugin;
+use NetAddr::IP;
+use File::Path qw(mkpath);
 our @ISA = qw(Mail::SpamAssassin::Plugin);
 
 sub new
@@ -104,8 +106,12 @@ sub greylisting
     }
     chomp($connectip);
     # Clean up input (for security, if you use files/dirs)
-    $connectip =~ /([\d.:]+)/;
-    $connectip = ($1 or "");
+
+    $connectip = NetAddr::IP->new($connectip);
+    if (not defined $connectip) {
+       warn "Can only handle IPv4 and IPv6 addresses; skipping greylisting call for message $mesgid\n";
+       return 0;
+    }
 
     # Account for a null envelope from
     if (not defined ($envfrom = $permsgstatus->get($option{'envfromhdr'})))
@@ -172,26 +178,27 @@ sub greylisting
           
            # connectip is supposed to be untainted now, but I was still getting
            # some insecure dependecy error messages sometimes (perl 5.8 problem apparently)
-           $connectip =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/;
-           my ($ipbyte1, $ipbyte2, $ipbyte3, $ipbyte4) = ($1, $2, $3, $4);
-           my $ipdir1 = "$option{'dir'}/$ipbyte1";
-           my $ipdir2 = "$ipdir1/$ipbyte2";
-           my $ipdir3 = "$ipdir2/$ipbyte3";
-           my $ipdir4;
-           my $tupletdir;
-
-           $ipdir4 = "$ipdir3";
-           $ipdir4 .= "/$ipbyte4" if ($option{'greylistfourthbyte'});
-           $tupletdir = "$ipdir4/$envfrom";
-
+           my $ipdir;
+           if ($connectip->version == 6) {
+               my @components = split ':', $connectip->full, 5;
+               if ($option{'greylistfourthbyte'}) {
+                   $ipdir = join '/', @components;
+               } else {
+                   $ipdir = join '/', @components[0..3];
+               }
+           } else {
+               my @components = split '\.', $connectip->addr;
+               if ($option{'greylistfourthbyte'}) {
+                   $ipdir = join '/', @components;
+               } else {
+                   $ipdir = join '/', @components[0..2];
+               }
+           }
+           my $tupletdir = "$option{'dir'}/$ipdir/$envfrom";
            $tuplet = "$tupletdir/$rcptto";
 
            # make directory whether it's there or not (faster than test and set)
-           mkdir $ipdir1;
-           mkdir $ipdir2;
-           mkdir $ipdir3;
-           mkdir $ipdir4;
-           mkdir $tupletdir;
+           mkpath $tupletdir;
 
            if (not -e $tuplet)
            {