You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by mm...@apache.org on 2015/05/23 15:58:40 UTC
svn commit: r1681350 - in /spamassassin/trunk/lib/Mail/SpamAssassin: Conf.pm
Plugin/WLBLEval.pm
Author: mmartinec
Date: Sat May 23 13:58:39 2015
New Revision: 1681350
URL: http://svn.apache.org/r1681350
Log:
Bug 7198: Let whitelist_from_rcvd also accept CIDR notation and IPv6 address
Modified:
spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/WLBLEval.pm
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm?rev=1681350&r1=1681349&r2=1681350&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm Sat May 23 13:58:39 2015
@@ -360,24 +360,24 @@ for the whitelisting rule to fire. The f
address to whitelist, and the second is a string to match the relay's rDNS,
or its IP address. Matching is case-insensitive.
-This second parameter is matched against the TCP-info information field as
-provided in a FROM clause of a trace information (i.e. the Received header
+This second parameter is matched against a TCP-info information field as
+provided in a FROM clause of a trace information (i.e. in a Received header
field, see RFC 5321). Only the Received header fields inserted by trusted
-hosts are considered. This parameter can either be a full hostname, or the
-domain component of that hostname, or an IP address in square brackets.
-The reverse DNS lookup is done by a MTA, not by SpamAssassin.
-
-In case of an IPv4 address in brackets, it may be truncated on classful
-boundaries to cover whole subnets, e.g. C<[10.1.2.3]>, C<[10.1.2]>,
-C<[10.1]>, C<[10]>. CIDR notation is currently not supported, nor is
-IPv6. The matching on IP address is mainly provided to cover rare cases
-where whitelisting of a sending MTA is desired which does not have a
-correct reverse DNS configured.
+hosts are considered. This parameter can either be a full hostname, or a
+domain component of that hostname, or an IP address (optionally followed
+by a slash and a prefix length) in square brackets. The address prefix
+(mask) length with a slash may stand within brackets along with an address,
+or may follow the bracketed address. Reverse DNS lookup is done by an MTA,
+not by SpamAssassin.
+
+For backward compatibility as an alternative to a CIDR notation, an IPv4
+address in brackets may be truncated on classful boundaries to cover whole
+subnets, e.g. C<[10.1.2.3]>, C<[10.1.2]>, C<[10.1]>, C<[10]>.
In other words, if the host that connected to your MX had an IP address
192.0.2.123 that mapped to 'sendinghost.example.org', you should specify
-C<sendinghost.example.org>, or C<example.org>, or C<[192.0.2.123]> or
-C<[192.0.2]> here.
+C<sendinghost.example.org>, or C<example.org>, or C<[192.0.2.123]>, or
+C<[192.0.2.0/24]>, or C<[192.0.2]> here.
Note that this requires that C<internal_networks> be correct. For simple
cases, it will be, but for a complex network you may get better results
@@ -390,8 +390,12 @@ result in the generated Received header
e.g.
whitelist_from_rcvd joe@example.com example.com
- whitelist_from_rcvd *@axkit.org sergeant.org
+ whitelist_from_rcvd *@* mail.example.org
whitelist_from_rcvd *@axkit.org [192.0.2.123]
+ whitelist_from_rcvd *@axkit.org [192.0.2.0/24]
+ whitelist_from_rcvd *@axkit.org [192.0.2.0]/24
+ whitelist_from_rcvd *@axkit.org [2001:db8:1234::/48]
+ whitelist_from_rcvd *@axkit.org [2001:db8:1234::]/48
=item def_whitelist_from_rcvd addr@lists.sourceforge.net sourceforge.net
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/WLBLEval.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/WLBLEval.pm?rev=1681350&r1=1681349&r2=1681350&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/WLBLEval.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/WLBLEval.pm Sat May 23 13:58:39 2015
@@ -17,14 +17,16 @@
package Mail::SpamAssassin::Plugin::WLBLEval;
-use Mail::SpamAssassin::Plugin;
-use Mail::SpamAssassin::Logger;
-
use strict;
use warnings;
use bytes;
use re 'taint';
+use NetAddr::IP 4.000;
+
+use Mail::SpamAssassin::Plugin;
+use Mail::SpamAssassin::Logger;
+
use vars qw(@ISA);
@ISA = qw(Mail::SpamAssassin::Plugin);
@@ -310,23 +312,51 @@ sub _check_whitelist_rcvd {
foreach my $white_addr (keys %{$list}) {
my $regexp = qr/$list->{$white_addr}{re}/i;
foreach my $domain (@{$list->{$white_addr}{domain}}) {
+ # $domain is a second param in whitelist_from_rcvd: a domain name or an IP address
if ($addr =~ $regexp) {
+ # From or sender address matching the first param in whitelist_from_rcvd
my $match;
foreach my $lastunt (@relays) {
- local $1;
- if ($domain =~ m{^ \[ (.*) \] \z}sx) { # matching by IP address
+ local($1,$2);
+ if ($domain =~ m{^ \[ (.*) \] ( / \d{1,3} )? \z}sx) {
+ # matching by IP address
my($wl_ip, $rly_ip) = ($1, $lastunt->{ip});
+ $wl_ip .= $2 if defined $2; # allow prefix len even after bracket
+
if (!defined $rly_ip || $rly_ip eq '') {
# relay's IP address not provided or unparseable
- } elsif ($wl_ip =~ /^\d+\.\d+\.\d+\.\d+\z/) {
+
+ } elsif ($wl_ip =~ /^\d+\.\d+\.\d+\.\d+\z/s) {
+ # an IPv4 whitelist entry can only be matched by an IPv4 relay
if ($wl_ip eq $rly_ip) { $match = 1; last } # exact match
- } elsif ($wl_ip =~ /^[\d\.]+\z/) { # assume IPv4 classful subnet
+
+ } elsif ($wl_ip =~ /^[\d\.]+\z/s) { # an IPv4 classful subnet?
$wl_ip =~ s/\.*\z/./; # enforce trailing dot
- if ($rly_ip =~ /^\Q$wl_ip\E/i) { $match = 1; last } # subnet
+ if ($rly_ip =~ /^\Q$wl_ip\E/) { $match = 1; last } # subnet
+
+ } else { # either an wl entry is an IPv6 addr, or has a prefix len
+ my $rly_ip_obj = NetAddr::IP->new($rly_ip); # TCP-info field
+ if (!defined $rly_ip_obj) {
+ dbg("rules: bad IP address in relay: %s, sender: %s",
+ $rly_ip, $addr);
+ } else {
+ my $wl_ip_obj = NetAddr::IP->new($wl_ip); # whitelist 2nd param
+ if (!defined $wl_ip_obj) {
+ info("rules: bad IP address in whitelist: %s", $wl_ip);
+ } elsif ($wl_ip_obj->contains($rly_ip_obj)) {
+ # note: an IPv4-compatible IPv6 address can match an IPv4 addr
+ dbg("rules: relay addr %s matches whitelist %s, sender: %s",
+ $rly_ip, $wl_ip_obj, $addr);
+ $match = 1; last;
+ } else {
+ dbg("rules: relay addr %s does not match wl %s, sender %s",
+ $rly_ip, $wl_ip_obj, $addr);
+ }
+ }
}
- # todo: handle IPv6 and CIDR notation
- } else { # match by a rdns name
+
+ } else { # match by an rdns name
my $rdns = $lastunt->{lc_rdns};
if ($rdns =~ /(?:^|\.)\Q${domain}\E$/i) { $match=1; last }
}