Hi,
Here comes patch hopefully fixing this issue. It needs to be applied in
/usr/share/perl5/Mail/SpamAssassin/Plugin
Here's what's changed:
- IPv6 addresses are validated and accepted
- directories are created from expanded IPv6 addresses, like
for example 2a01:ff::1 gives 2A01/0000/0000/0000/0000/0000/00FF/0001
so paths are distinct from IPv4 based ones and easily recognisable
- greylistfourthbyte configuration setting is aliased to
grelistsingleipv4
and made optional (resolves to false if not defined) to unify it with
newly added settings
- two new optional configuration settings are defined:
- greylistsingleipv6 - similar to greylistssingleipv4, if not
defined as true
whole /64 subnet gets whitelisted
- greylistsingleip - convenience option for setting both
greylistssingleipv[46] to true
- directory tree creation procedure is cleaned up by using mkpath
- new dependency introduced: netaddr-ip-perl, but as it is
dependency of spamassassin
already, may be given as Suggests/Recommends only
- IPv4 validation is more strict (still not perfect...) so
additional regexp got dropped
What's left is documenting new options in README.greylisting.gz
Please review and apply if feasible or you may contact me if
something needs
to be improved or fixed.
regards,
Robert Tasarz
diff --git a/Greylisting.pm b/Greylisting.pm
--- a/Greylisting.pm
+++ b/Greylisting.pm
@@ -21,6 +21,8 @@
use strict;
use Mail::SpamAssassin::Plugin;
+use NetAddr::IP::Util qw(ipv6_aton ipv6_n2x);
+use File::Path qw(mkpath);
our @ISA = qw(Mail::SpamAssassin::Plugin);
sub new
@@ -71,7 +73,7 @@
$self->{'rangreylisting'}=1;
foreach my $reqoption (qw ( method greylistsecs dontgreylistthreshold
- connectiphdr envfromhdr rcpttohdr greylistnullfrom greylistfourthbyte ))
+ connectiphdr envfromhdr rcpttohdr greylistnullfrom ))
{
die "Greylist option $reqoption missing from SA config" unless (defined $option{$reqoption});
}
@@ -104,8 +106,19 @@
}
chomp($connectip);
# Clean up input (for security, if you use files/dirs)
- $connectip =~ /([\d.:]+)/;
- $connectip = ($1 or "");
+
+ # Checking for valid IPv6 address
+ eval {
+ $connectip = ipv6_n2x ipv6_aton $connectip;
+ };
+ if (not $@) {
+ # Expanding ipv6 with leading zeroes so it is easier to visually differentiate it from ipv4
+ $connectip =~ s/([\da-f]+)/$|x(4-length($1)).$1/gie;
+ }
+ else {
+ $connectip =~ /^([\d.]+)$/;
+ $connectip = ($1 or "");
+ }
# Account for a null envelope from
if (not defined ($envfrom = $permsgstatus->get($option{'envfromhdr'})))
@@ -170,31 +183,23 @@
die "greylist option dir not passed, even though method was set to dir" unless ($option{'dir'});
- # connectip is supposed to be untainted now, but I was still getting
- # some insecure dependecy error messages sometimes (perl 5.8 problem apparently)
- unless ($connectip =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/) {
- warn "Can only handle IPv4 addresses; skipping greylisting call for message $mesgid\n";
+ if (not $connectip) {
+ warn "Can only handle IPv4 and IPv6 addresses; skipping greylisting call for message $mesgid\n";
return 0;
}
- my $ipdir1 = "$option{'dir'}/$1";
- my $ipdir2 = "$ipdir1/$2";
- my $ipdir3 = "$ipdir2/$3";
- my $ipdir4;
- my $tupletdir;
+ my $ipdir = $connectip;
+ $ipdir = substr($ipdir, 0, 19) if not ($option{'greylistsingleipv6'} or $option{'greylistsingleip'});
+ $ipdir =~ s/\.\d+$// if not ($option{'greylistfourthbyte'} or $option{'greylistsingleipv4'} or $option{'greylistsingleip'});
- $ipdir4 = "$ipdir3";
- $ipdir4 .= "/$4" if ($option{'greylistfourthbyte'});
- $tupletdir = "$ipdir4/$envfrom";
+ $ipdir =~ s/[:.]/\//g;
+
+ 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)
{