From 335460b8d34401e0e1ebb77628e158011dc5c80d Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: May 10 2022 07:07:14 +0000 Subject: import spamassassin-3.4.6-1.el8 --- diff --git a/.gitignore b/.gitignore index bc510d9..b1e78dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -SOURCES/Mail-SpamAssassin-3.4.4.tar.bz2 -SOURCES/Mail-SpamAssassin-rules-3.4.4.r1873061.tgz +SOURCES/Mail-SpamAssassin-3.4.6.tar.bz2 +SOURCES/Mail-SpamAssassin-rules-3.4.6.r1888502.tgz diff --git a/.spamassassin.metadata b/.spamassassin.metadata index cd26fa1..00d5b3d 100644 --- a/.spamassassin.metadata +++ b/.spamassassin.metadata @@ -1,2 +1,2 @@ -23ab1edb89570c0367c117cbaf1e816c0dc1fb90 SOURCES/Mail-SpamAssassin-3.4.4.tar.bz2 -ee022f1cc18a66d49c1954936c70c36049c37dcf SOURCES/Mail-SpamAssassin-rules-3.4.4.r1873061.tgz +26390aa8c9176c7d280252e4f01defe031373d32 SOURCES/Mail-SpamAssassin-3.4.6.tar.bz2 +bc4a64ed49f6df75d6bce8396fa476548a66d755 SOURCES/Mail-SpamAssassin-rules-3.4.6.r1888502.tgz diff --git a/SOURCES/0001-Drop-the-ResourceLimits-plugin.patch b/SOURCES/0001-Drop-the-ResourceLimits-plugin.patch deleted file mode 100644 index 61798f4..0000000 --- a/SOURCES/0001-Drop-the-ResourceLimits-plugin.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff --git a/MANIFEST b/MANIFEST -index c4aca1b..5ba3a0c 100644 ---- a/MANIFEST -+++ b/MANIFEST -@@ -101,7 +101,6 @@ lib/Mail/SpamAssassin/Plugin/Pyzor.pm - lib/Mail/SpamAssassin/Plugin/Razor2.pm - lib/Mail/SpamAssassin/Plugin/RelayCountry.pm - lib/Mail/SpamAssassin/Plugin/RelayEval.pm --lib/Mail/SpamAssassin/Plugin/ResourceLimits.pm - lib/Mail/SpamAssassin/Plugin/ReplaceTags.pm - lib/Mail/SpamAssassin/Plugin/Reuse.pm - lib/Mail/SpamAssassin/Plugin/Rule2XSBody.pm -diff --git a/lib/Mail/SpamAssassin/Util/DependencyInfo.pm b/lib/Mail/SpamAssassin/Util/DependencyInfo.pm -index eca12e1..9a6b4fb 100644 ---- a/lib/Mail/SpamAssassin/Util/DependencyInfo.pm -+++ b/lib/Mail/SpamAssassin/Util/DependencyInfo.pm -@@ -233,12 +233,6 @@ our @OPTIONAL_MODULES = ( - check for both Net::DNS and Net::DNS::Nameserver. However, - Net::DNS::Nameserver is only used in make test as of June 2014.', - }, --{ -- module => 'BSD::Resource', -- version => 0, -- desc => 'BSD::Resource provides BSD process resource limit and priority -- functions. It is used by the optional ResourceLimits Plugin.', --}, - { - module => 'Archive::Zip', - version => 0, -diff --git a/rules/v342.pre b/rules/v342.pre -index 8e0fb07..c4758e9 100644 ---- a/rules/v342.pre -+++ b/rules/v342.pre -@@ -19,10 +19,6 @@ - # HashBL - Query hashed/unhashed strings, emails, uris etc from DNS lists - # loadplugin Mail::SpamAssassin::Plugin::HashBL - --# ResourceLimits - assure your spamd child processes --# do not exceed specified CPU or memory limit --# loadplugin Mail::SpamAssassin::Plugin::ResourceLimits -- - # FromNameSpoof - help stop spam that tries to spoof other domains using - # the from name - # loadplugin Mail::SpamAssassin::Plugin::FromNameSpoof diff --git a/SOURCES/spamassassin-3.4.2-drop-geoip.patch b/SOURCES/spamassassin-3.4.2-drop-geoip.patch deleted file mode 100644 index 74ceeab..0000000 --- a/SOURCES/spamassassin-3.4.2-drop-geoip.patch +++ /dev/null @@ -1,1234 +0,0 @@ -diff --git a/MANIFEST b/MANIFEST -index a988fa1..c4aca1b 100644 ---- a/MANIFEST -+++ b/MANIFEST -@@ -118,7 +118,6 @@ lib/Mail/SpamAssassin/Plugin/VBounce.pm - lib/Mail/SpamAssassin/Plugin/WLBLEval.pm - lib/Mail/SpamAssassin/Plugin/WhiteListSubject.pm - lib/Mail/SpamAssassin/PluginHandler.pm --lib/Mail/SpamAssassin/Plugin/URILocalBL.pm - lib/Mail/SpamAssassin/RegistryBoundaries.pm - lib/Mail/SpamAssassin/Reporter.pm - lib/Mail/SpamAssassin/SQLBasedAddrList.pm -diff --git a/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm b/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm -deleted file mode 100644 -index 38ec1e3..0000000 ---- a/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm -+++ /dev/null -@@ -1,407 +0,0 @@ --# <@LICENSE> --# Licensed to the Apache Software Foundation (ASF) under one or more --# contributor license agreements. See the NOTICE file distributed with --# this work for additional information regarding copyright ownership. --# The ASF licenses this file to you under the Apache License, Version 2.0 --# (the "License"); you may not use this file except in compliance with --# the License. You may obtain a copy of the License at: --# --# http://www.apache.org/licenses/LICENSE-2.0 --# --# Unless required by applicable law or agreed to in writing, software --# distributed under the License is distributed on an "AS IS" BASIS, --# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --# See the License for the specific language governing permissions and --# limitations under the License. --# -- --=head1 NAME -- --RelayCountry - add message metadata indicating the country code of each relay -- --=head1 SYNOPSIS -- -- loadplugin Mail::SpamAssassin::Plugin::RelayCountry -- --=head1 DESCRIPTION -- --The RelayCountry plugin attempts to determine the domain country codes --of each relay used in the delivery path of messages and add that information --to the message metadata. -- --Following metadata headers and tags are added: -- -- X-Relay-Countries _RELAYCOUNTRY_ -- All untrusted relays. Contains all relays starting from the -- trusted_networks border. This method has been used by default since -- early SA versions. -- -- X-Relay-Countries-External _RELAYCOUNTRYEXT_ -- All external relays. Contains all relays starting from the -- internal_networks border. Could be useful in some cases when -- trusted/msa_networks extend beyond the internal border and those -- need to be checked too. -- -- X-Relay-Countries-All _RELAYCOUNTRYALL_ -- All possible relays (internal + external). -- -- X-Relay-Countries-Auth _RELAYCOUNTRYAUTH_ -- Auth will contain all relays starting from the first relay that used -- authentication. For example, this could be used to check for hacked -- local users coming in from unexpected countries. If there are no -- authenticated relays, this will be empty. -- --=head1 REQUIREMENT -- --This plugin requires the GeoIP2, Geo::IP, IP::Country::DB_File or --IP::Country::Fast module from CPAN. --For backward compatibility IP::Country::Fast is used as fallback if no db_type --is specified in the config file. -- --=cut -- --package Mail::SpamAssassin::Plugin::RelayCountry; -- --use Mail::SpamAssassin::Plugin; --use Mail::SpamAssassin::Logger; --use Mail::SpamAssassin::Constants qw(:ip); --use strict; --use warnings; --# use bytes; --use re 'taint'; -- --our @ISA = qw(Mail::SpamAssassin::Plugin); -- --# constructor: register the eval rule --sub new { -- my $class = shift; -- my $mailsaobject = shift; -- -- # some boilerplate... -- $class = ref($class) || $class; -- my $self = $class->SUPER::new($mailsaobject); -- bless ($self, $class); -- -- $self->set_config($mailsaobject->{conf}); -- return $self; --} -- --sub set_config { -- my ($self, $conf) = @_; -- my @cmds; -- --=head1 USER PREFERENCES -- --The following options can be used in both site-wide (C) and --user-specific (C) configuration files to customize how --SpamAssassin handles incoming email messages. -- --=over 4 -- --=item country_db_type STRING -- --This option tells SpamAssassin which type of Geo database to use. --Valid database types are GeoIP, GeoIP2, DB_File and Fast. -- --=back -- --=cut -- -- push (@cmds, { -- setting => 'country_db_type', -- default => "GeoIP", -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- if ($value !~ /^(?:GeoIP|GeoIP2|DB_File|Fast)$/) { -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- $self->{country_db_type} = $value; -- } -- }); -- --=over 4 -- --=item country_db_path STRING -- --This option tells SpamAssassin where to find MaxMind GeoIP2 or IP::Country::DB_File database. -- --If not defined, GeoIP2 default search includes: -- /usr/local/share/GeoIP/GeoIP2-Country.mmdb -- /usr/share/GeoIP/GeoIP2-Country.mmdb -- /var/lib/GeoIP/GeoIP2-Country.mmdb -- /usr/local/share/GeoIP/GeoLite2-Country.mmdb -- /usr/share/GeoIP/GeoLite2-Country.mmdb -- /var/lib/GeoIP/GeoLite2-Country.mmdb -- (and same paths again for -City.mmdb, which also has country functionality) -- --=back -- --=cut -- -- push (@cmds, { -- setting => 'country_db_path', -- default => "", -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- if (!defined $value || !length $value) { -- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; -- } -- if (!-e $value) { -- info("config: country_db_path \"$value\" is not accessible"); -- $self->{country_db_path} = $value; -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- $self->{country_db_path} = $value; -- } -- }); -- -- push (@cmds, { -- setting => 'geoip2_default_db_path', -- default => [ -- '/usr/local/share/GeoIP/GeoIP2-Country.mmdb', -- '/usr/share/GeoIP/GeoIP2-Country.mmdb', -- '/var/lib/GeoIP/GeoIP2-Country.mmdb', -- '/usr/local/share/GeoIP/GeoLite2-Country.mmdb', -- '/usr/share/GeoIP/GeoLite2-Country.mmdb', -- '/var/lib/GeoIP/GeoLite2-Country.mmdb', -- '/usr/local/share/GeoIP/GeoIP2-City.mmdb', -- '/usr/share/GeoIP/GeoIP2-City.mmdb', -- '/var/lib/GeoIP/GeoIP2-City.mmdb', -- '/usr/local/share/GeoIP/GeoLite2-City.mmdb', -- '/usr/share/GeoIP/GeoLite2-City.mmdb', -- '/var/lib/GeoIP/GeoLite2-City.mmdb', -- ], -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRINGLIST, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- if ($value eq '') { -- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; -- } -- push(@{$self->{geoip2_default_db_path}}, split(/\s+/, $value)); -- } -- }); -- -- $conf->{parser}->register_commands(\@cmds); --} -- --sub get_country { -- my ($self, $ip, $db, $dbv6, $country_db_type) = @_; -- my $cc; -- my $IP_PRIVATE = IP_PRIVATE; -- my $IPV4_ADDRESS = IPV4_ADDRESS; -- -- # Private IPs will always be returned as '**' -- if ($ip =~ /^$IP_PRIVATE$/o) { -- $cc = "**"; -- } -- elsif ($country_db_type eq "GeoIP") { -- if ($ip =~ /^$IPV4_ADDRESS$/o) { -- $cc = $db->country_code_by_addr($ip); -- } elsif (defined $dbv6) { -- $cc = $dbv6->country_code_by_addr_v6($ip); -- } -- } -- elsif ($country_db_type eq "GeoIP2") { -- my ($country, $country_rec); -- eval { -- if (index($db->metadata()->description()->{en}, 'City') != -1) { -- $country = $db->city( ip => $ip ); -- } else { -- $country = $db->country( ip => $ip ); -- } -- $country_rec = $country->country(); -- $cc = $country_rec->iso_code(); -- 1; -- } or do { -- $@ =~ s/\s+Trace begun.*//s; -- dbg("metadata: RelayCountry: GeoIP2 failed: $@"); -- } -- } -- elsif ($country_db_type eq "DB_File") { -- if ($ip =~ /^$IPV4_ADDRESS$/o ) { -- $cc = $db->inet_atocc($ip); -- } else { -- $cc = $db->inet6_atocc($ip); -- } -- } -- elsif ($country_db_type eq "Fast") { -- $cc = $db->inet_atocc($ip); -- } -- -- $cc ||= 'XX'; -- -- return $cc; --} -- --sub extract_metadata { -- my ($self, $opts) = @_; -- my $pms = $opts->{permsgstatus}; -- -- my $db; -- my $dbv6; -- my $db_info; # will hold database info -- my $db_type; # will hold database type -- -- my $country_db_type = $opts->{conf}->{country_db_type}; -- my $country_db_path = $opts->{conf}->{country_db_path}; -- -- if ($country_db_type eq "GeoIP") { -- eval { -- require Geo::IP; -- $db = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION, Geo::IP->GEOIP_STANDARD); -- die "GeoIP.dat not found" unless $db; -- # IPv6 requires version Geo::IP 1.39+ with GeoIP C API 1.4.7+ -- if (Geo::IP->VERSION >= 1.39 && Geo::IP->api eq 'CAPI') { -- $dbv6 = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION_V6, Geo::IP->GEOIP_STANDARD); -- if (!$dbv6) { -- dbg("metadata: RelayCountry: GeoIP: IPv6 support not enabled, GeoIPv6.dat not found"); -- } -- } else { -- dbg("metadata: RelayCountry: GeoIP: IPv6 support not enabled, versions Geo::IP 1.39, GeoIP C API 1.4.7 required"); -- } -- $db_info = sub { return "Geo::IP IPv4: " . ($db->database_info || '?')." / IPv6: ".($dbv6 ? $dbv6->database_info || '?' : '?') }; -- 1; -- } or do { -- # Fallback to IP::Country::Fast -- dbg("metadata: RelayCountry: GeoIP: GeoIP.dat not found, trying IP::Country::Fast as fallback"); -- $country_db_type = "Fast"; -- } -- } -- elsif ($country_db_type eq "GeoIP2") { -- if (!$country_db_path) { -- # Try some default locations -- foreach (@{$opts->{conf}->{geoip2_default_db_path}}) { -- if (-f $_) { -- $country_db_path = $_; -- last; -- } -- } -- } -- if (-f $country_db_path) { -- eval { -- require GeoIP2::Database::Reader; -- $db = GeoIP2::Database::Reader->new( -- file => $country_db_path, -- locales => [ 'en' ] -- ); -- die "unknown error" unless $db; -- $db_info = sub { -- my $m = $db->metadata(); -- return "GeoIP2 ".$m->description()->{en}." / ".localtime($m->build_epoch()); -- }; -- 1; -- } or do { -- # Fallback to IP::Country::Fast -- $@ =~ s/\s+Trace begun.*//s; -- dbg("metadata: RelayCountry: GeoIP2: ${country_db_path} load failed: $@, trying IP::Country::Fast as fallback"); -- $country_db_type = "Fast"; -- } -- } else { -- # Fallback to IP::Country::Fast -- my $err = $country_db_path ? -- "$country_db_path not found" : "database not found from default locations"; -- dbg("metadata: RelayCountry: GeoIP2: $err, trying IP::Country::Fast as fallback"); -- $country_db_type = "Fast"; -- } -- } -- elsif ($country_db_type eq "DB_File") { -- if (-f $country_db_path) { -- eval { -- require IP::Country::DB_File; -- $db = IP::Country::DB_File->new($country_db_path); -- die "unknown error" unless $db; -- $db_info = sub { return "IP::Country::DB_File ".localtime($db->db_time()); }; -- 1; -- } or do { -- # Fallback to IP::Country::Fast -- dbg("metadata: RelayCountry: DB_File: ${country_db_path} load failed: $@, trying IP::Country::Fast as fallback"); -- $country_db_type = "Fast"; -- } -- } else { -- # Fallback to IP::Country::Fast -- dbg("metadata: RelayCountry: DB_File: ${country_db_path} not found, trying IP::Country::Fast as fallback"); -- $country_db_type = "Fast"; -- } -- } -- -- if ($country_db_type eq "Fast") { -- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat; -- eval { -- require IP::Country::Fast; -- $db = IP::Country::Fast->new(); -- $db_info = sub { return "IP::Country::Fast ".localtime($db->db_time()); }; -- 1; -- } or do { -- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat; -- dbg("metadata: RelayCountry: failed to load 'IP::Country::Fast', skipping: $eval_stat"); -- return 1; -- } -- } -- -- if (!$db) { -- return 1; -- } -- -- dbg("metadata: RelayCountry: Using database: ".$db_info->()); -- my $msg = $opts->{msg}; -- -- my @cc_untrusted; -- foreach my $relay (@{$msg->{metadata}->{relays_untrusted}}) { -- my $ip = $relay->{ip}; -- my $cc = $self->get_country($ip, $db, $dbv6, $country_db_type); -- push @cc_untrusted, $cc; -- } -- -- my @cc_external; -- foreach my $relay (@{$msg->{metadata}->{relays_external}}) { -- my $ip = $relay->{ip}; -- my $cc = $self->get_country($ip, $db, $dbv6, $country_db_type); -- push @cc_external, $cc; -- } -- -- my @cc_auth; -- my $found_auth; -- foreach my $relay (@{$msg->{metadata}->{relays_trusted}}) { -- if ($relay->{auth}) { -- $found_auth = 1; -- } -- if ($found_auth) { -- my $ip = $relay->{ip}; -- my $cc = $self->get_country($ip, $db, $dbv6, $country_db_type); -- push @cc_auth, $cc; -- } -- } -- -- my @cc_all; -- foreach my $relay (@{$msg->{metadata}->{relays_internal}}, @{$msg->{metadata}->{relays_external}}) { -- my $ip = $relay->{ip}; -- my $cc = $self->get_country($ip, $db, $dbv6, $country_db_type); -- push @cc_all, $cc; -- } -- -- my $ccstr = join(' ', @cc_untrusted); -- $msg->put_metadata("X-Relay-Countries", $ccstr); -- dbg("metadata: X-Relay-Countries: $ccstr"); -- $pms->set_tag("RELAYCOUNTRY", @cc_untrusted == 1 ? $cc_untrusted[0] : \@cc_untrusted); -- -- $ccstr = join(' ', @cc_external); -- $msg->put_metadata("X-Relay-Countries-External", $ccstr); -- dbg("metadata: X-Relay-Countries-External: $ccstr"); -- $pms->set_tag("RELAYCOUNTRYEXT", @cc_external == 1 ? $cc_external[0] : \@cc_external); -- -- $ccstr = join(' ', @cc_auth); -- $msg->put_metadata("X-Relay-Countries-Auth", $ccstr); -- dbg("metadata: X-Relay-Countries-Auth: $ccstr"); -- $pms->set_tag("RELAYCOUNTRYAUTH", @cc_auth == 1 ? $cc_auth[0] : \@cc_auth); -- -- $ccstr = join(' ', @cc_all); -- $msg->put_metadata("X-Relay-Countries-All", $ccstr); -- dbg("metadata: X-Relay-Countries-All: $ccstr"); -- $pms->set_tag("RELAYCOUNTRYALL", @cc_all == 1 ? $cc_all[0] : \@cc_all); -- -- return 1; --} -- --1; -diff --git a/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm b/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm -deleted file mode 100644 -index 4fbbcb7..0000000 ---- a/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm -+++ /dev/null -@@ -1,705 +0,0 @@ --# <@LICENSE> --# Licensed to the Apache Software Foundation (ASF) under one or more --# contributor license agreements. See the NOTICE file distributed with --# this work for additional information regarding copyright ownership. --# The ASF licenses this file to you under the Apache License, Version 2.0 --# (the "License"); you may not use this file except in compliance with --# the License. You may obtain a copy of the License at: --# --# http://www.apache.org/licenses/LICENSE-2.0 --# --# Unless required by applicable law or agreed to in writing, software --# distributed under the License is distributed on an "AS IS" BASIS, --# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --# See the License for the specific language governing permissions and --# limitations under the License. --# -- --=head1 NAME -- --URILocalBL - blacklist URIs using local information (ISP names, address lists, and country codes) -- --=head1 SYNOPSIS -- --This plugin creates some new rule test types, such as "uri_block_cc", --"uri_block_cidr", and "uri_block_isp". These rules apply to the URIs --found in the HTML portion of a message, i.e. markup. -- -- loadplugin Mail::SpamAssassin::Plugin::URILocalBL -- --Why local blacklisting? There are a few excellent, effective, and --well-maintained DNSBL's out there. But they have several drawbacks: -- --=over 2 -- --=item * blacklists can cover tens of thousands of entries, and you can't select which ones you use; -- --=item * verifying that it's correctly configured can be non-trivial; -- --=item * new blacklisting entries may take a while to be detected and entered, so it's not instantaneous. -- --=back -- --Sometimes all you want is a quick, easy, and very surgical blacklisting of --a particular site or a particular ISP. This plugin is defined for that --exact usage case. -- --=head1 RULE DEFINITIONS AND PRIVILEGED SETTINGS -- --The format for defining a rule is as follows: -- -- uri_block_cc SYMBOLIC_TEST_NAME cc1 cc2 cc3 cc4 -- --or: -- -- uri_block_cont SYMBOLIC_TEST_NAME co1 co2 co3 co4 -- --or: -- -- uri_block_cidr SYMBOLIC_TEST_NAME a.a.a.a b.b.b.b/cc d.d.d.d-e.e.e.e -- --or: -- -- uri_block_isp SYMBOLIC_TEST_NAME "DataRancid" "McCarrier" "Phishers-r-Us" -- --Example rule for matching a URI in China: -- -- uri_block_cc TEST1 cn -- --This would block the URL http://www.baidu.com/index.htm. Similarly, to --match a Spam-haven netblock: -- -- uri_block_cidr TEST2 65.181.64.0/18 -- --would match a netblock where several phishing sites were recently hosted. -- --And to block all CIDR blocks registered to an ISP, one might use: -- -- uri_block_isp TEST3 "ColoCrossing" -- --if one didn't trust URL's pointing to that organization's clients. Lastly, --if there's a country that you want to block but there's an explicit host --you wish to exempt from that blacklist, you can use: -- -- uri_block_exclude TEST1 www.baidu.com -- --if you wish to exempt URL's referring to this host. The same syntax is --applicable to CIDR and ISP blocks as well. -- --=head1 DEPENDENCIES -- --The Country-Code based filtering requires the Geo::IP or GeoIP2 module, --which uses either the fremium GeoLiteCountry database, or the commercial --version of it called GeoIP from MaxMind.com. -- --The ISP based filtering requires the same module, plus the GeoIPISP database. --There is no fremium version of this database, so commercial licensing is --required. -- --=cut -- --package Mail::SpamAssassin::Plugin::URILocalBL; --use Mail::SpamAssassin::Plugin; --use Mail::SpamAssassin::Logger; --use Mail::SpamAssassin::Constants qw(:ip); --use Mail::SpamAssassin::Util qw(untaint_var); -- --use Socket; -- --use strict; --use warnings; --# use bytes; --use re 'taint'; --use version; -- --our @ISA = qw(Mail::SpamAssassin::Plugin); -- --use constant HAS_GEOIP => eval { require Geo::IP; }; --use constant HAS_GEOIP2 => eval { require GeoIP2::Database::Reader; }; --use constant HAS_CIDR => eval { require Net::CIDR::Lite; }; -- --# constructor --sub new { -- my $class = shift; -- my $mailsaobject = shift; -- -- # some boilerplate... -- $class = ref($class) || $class; -- my $self = $class->SUPER::new($mailsaobject); -- bless ($self, $class); -- -- # how to handle failure to get the database handle? -- # and we don't really have a valid return value... -- # can we defer getting this handle until we actually see -- # a uri_block_cc rule? -- -- $self->register_eval_rule("check_uri_local_bl"); -- -- $self->set_config($mailsaobject->{conf}); -- -- return $self; --} -- --sub set_config { -- my ($self, $conf) = @_; -- my @cmds; -- -- my $pluginobj = $self; # allow use inside the closure below -- -- push (@cmds, { -- setting => 'uri_block_cc', -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, -- is_priv => 1, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- -- if ($value !~ /^(\S+)\s+(.+)$/) { -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- my $name = $1; -- my $def = $2; -- my $added_criteria = 0; -- -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{countries} = {}; -- -- # this should match all country codes including satellite providers -- while ($def =~ m/^\s*([a-z][a-z0-9])(\s+(.*)|)$/) { -- my $cc = $1; -- my $rest = $2; -- -- #dbg("config: uri_block_cc adding %s to %s\n", $cc, $name); -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{countries}->{uc($cc)} = 1; -- $added_criteria = 1; -- -- $def = $rest; -- } -- -- if ($added_criteria == 0) { -- warn "config: no arguments"; -- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; -- } elsif ($def ne '') { -- warn "config: failed to add invalid rule $name"; -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- -- dbg("config: uri_block_cc added %s\n", $name); -- -- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); -- } -- }); -- -- push (@cmds, { -- setting => 'uri_block_cont', -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, -- is_priv => 1, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- -- if ($value !~ /^(\S+)\s+(.+)$/) { -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- my $name = $1; -- my $def = $2; -- my $added_criteria = 0; -- -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{continents} = {}; -- -- # this should match all continent codes -- while ($def =~ m/^\s*([a-z]{2})(\s+(.*)|)$/) { -- my $cont = $1; -- my $rest = $2; -- -- # dbg("config: uri_block_cont adding %s to %s\n", $cont, $name); -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{continents}->{uc($cont)} = 1; -- $added_criteria = 1; -- -- $def = $rest; -- } -- -- if ($added_criteria == 0) { -- warn "config: no arguments"; -- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; -- } elsif ($def ne '') { -- warn "config: failed to add invalid rule $name"; -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- -- dbg("config: uri_block_cont added %s\n", $name); -- -- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); -- } -- }); -- -- push (@cmds, { -- setting => 'uri_block_isp', -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, -- is_priv => 1, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- -- if ($value !~ /^(\S+)\s+(.+)$/) { -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- my $name = $1; -- my $def = $2; -- my $added_criteria = 0; -- -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{isps} = {}; -- -- # gather up quoted strings -- while ($def =~ m/^\s*"([^"]*)"(\s+(.*)|)$/) { -- my $isp = $1; -- my $rest = $2; -- -- dbg("config: uri_block_isp adding \"%s\" to %s\n", $isp, $name); -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{isps}->{$isp} = 1; -- $added_criteria = 1; -- -- $def = $rest; -- } -- -- if ($added_criteria == 0) { -- warn "config: no arguments"; -- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; -- } elsif ($def ne '') { -- warn "config: failed to add invalid rule $name"; -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- -- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); -- } -- }); -- -- push (@cmds, { -- setting => 'uri_block_cidr', -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, -- is_priv => 1, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- -- if (!HAS_CIDR) { -- warn "config: uri_block_cidr not supported, required module Net::CIDR::Lite missing\n"; -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- -- if ($value !~ /^(\S+)\s+(.+)$/) { -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- my $name = $1; -- my $def = $2; -- my $added_criteria = 0; -- -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{cidr} = new Net::CIDR::Lite; -- -- # match individual IP's, subnets, and ranges -- while ($def =~ m/^\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2}|-\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?)(\s+(.*)|)$/) { -- my $addr = $1; -- my $rest = $3; -- -- dbg("config: uri_block_cidr adding %s to %s\n", $addr, $name); -- -- eval { $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{cidr}->add_any($addr) }; -- last if ($@); -- -- $added_criteria = 1; -- -- $def = $rest; -- } -- -- if ($added_criteria == 0) { -- warn "config: no arguments"; -- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; -- } elsif ($def ne '') { -- warn "config: failed to add invalid rule $name"; -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- -- # optimize the ranges -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{cidr}->clean(); -- -- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); -- } -- }); -- -- push (@cmds, { -- setting => 'uri_block_exclude', -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, -- is_priv => 1, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- -- if ($value !~ /^(\S+)\s+(.+)$/) { -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- my $name = $1; -- my $def = $2; -- my $added_criteria = 0; -- -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{exclusions} = {}; -- -- # match individual IP's, or domain names -- while ($def =~ m/^\s*((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(([a-z0-9][-a-z0-9]*[a-z0-9](\.[a-z0-9][-a-z0-9]*[a-z0-9]){1,})))(\s+(.*)|)$/) { -- my $addr = $1; -- my $rest = $6; -- -- dbg("config: uri_block_exclude adding %s to %s\n", $addr, $name); -- -- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{exclusions}->{$addr} = 1; -- -- $added_criteria = 1; -- -- $def = $rest; -- } -- -- if ($added_criteria == 0) { -- warn "config: no arguments"; -- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; -- } elsif ($def ne '') { -- warn "config: failed to add invalid rule $name"; -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- -- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); -- } -- }); -- --=over 2 -- --=item uri_country_db_path STRING -- --This option tells SpamAssassin where to find the MaxMind country GeoIP2 --database. Country or City database are both supported. -- --=back -- --=cut -- -- push (@cmds, { -- setting => 'uri_country_db_path', -- is_priv => 1, -- default => undef, -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- if (!defined $value || !length $value) { -- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; -- } -- if (!-f $value) { -- info("config: uri_country_db_path \"$value\" is not accessible"); -- $self->{uri_country_db_path} = $value; -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- -- $self->{uri_country_db_path} = $value; -- } -- }); -- --=over 2 -- --=item uri_country_db_isp_path STRING -- --This option tells SpamAssassin where to find the MaxMind isp GeoIP2 database. -- --=back -- --=cut -- -- push (@cmds, { -- setting => 'uri_country_db_isp_path', -- is_priv => 1, -- default => undef, -- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, -- code => sub { -- my ($self, $key, $value, $line) = @_; -- if (!defined $value || !length $value) { -- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; -- } -- if (!-f $value) { -- info("config: uri_country_db_isp_path \"$value\" is not accessible"); -- $self->{uri_country_db_isp_path} = $value; -- return $Mail::SpamAssassin::Conf::INVALID_VALUE; -- } -- -- $self->{uri_country_db_isp_path} = $value; -- } -- }); -- -- $conf->{parser}->register_commands(\@cmds); --} -- --sub check_uri_local_bl { -- my ($self, $permsg) = @_; -- -- my $cc; -- my $cont; -- my $db_info; -- my $isp; -- -- my $conf_country_db_path = $self->{'main'}{'resolver'}{'conf'}->{uri_country_db_path}; -- my $conf_country_db_isp_path = $self->{'main'}{'resolver'}{'conf'}->{uri_country_db_isp_path}; -- # If country_db_path is set I am using GeoIP2 api -- if ( HAS_GEOIP2 and ( ( defined $conf_country_db_path ) or ( defined $conf_country_db_isp_path ) ) ) { -- -- eval { -- $self->{geoip} = GeoIP2::Database::Reader->new( -- file => $conf_country_db_path, -- locales => [ 'en' ] -- ) if (( defined $conf_country_db_path ) && ( -f $conf_country_db_path)); -- if ( defined ($conf_country_db_path) ) { -- $db_info = sub { return "GeoIP2 " . ($self->{geoip}->metadata()->description()->{en} || '?') }; -- warn "$conf_country_db_path not found" unless $self->{geoip}; -- } -- -- $self->{geoisp} = GeoIP2::Database::Reader->new( -- file => $conf_country_db_isp_path, -- locales => [ 'en' ] -- ) if (( defined $conf_country_db_isp_path ) && ( -f $conf_country_db_isp_path)); -- if ( defined ($conf_country_db_isp_path) ) { -- warn "$conf_country_db_isp_path not found" unless $self->{geoisp}; -- } -- $self->{use_geoip2} = 1; -- }; -- if ($@ || !($self->{geoip} || $self->{geoisp})) { -- $@ =~ s/\s+Trace begun.*//s; -- warn "URILocalBL: GeoIP2 load failed: $@\n"; -- return 0; -- } -- -- } elsif ( HAS_GEOIP ) { -- BEGIN { -- Geo::IP->import( qw(GEOIP_MEMORY_CACHE GEOIP_CHECK_CACHE GEOIP_ISP_EDITION) ); -- } -- $self->{use_geoip2} = 0; -- # need GeoIP C library 1.6.3 and GeoIP perl API 1.4.4 or later to avoid messages leaking - Bug 7153 -- my $gic_wanted = version->parse('v1.6.3'); -- my $gic_have = version->parse(Geo::IP->lib_version()); -- my $gip_wanted = version->parse('v1.4.4'); -- my $gip_have = version->parse($Geo::IP::VERSION); -- -- # this code burps an ugly message if it fails, but that's redirected elsewhere -- my $flags = 0; -- my $flag_isp = 0; -- my $flag_silent = 0; -- eval '$flags = GEOIP_MEMORY_CACHE | GEOIP_CHECK_CACHE' if ($gip_wanted >= $gip_have); -- eval '$flag_silent = Geo::IP::GEOIP_SILENCE' if ($gip_wanted >= $gip_have); -- eval '$flag_isp = GEOIP_ISP_EDITION' if ($gip_wanted >= $gip_have); -- -- eval { -- if ($flag_silent && $gic_wanted >= $gic_have) { -- $self->{geoip} = Geo::IP->new($flags | $flag_silent); -- $self->{geoisp} = Geo::IP->open_type($flag_isp | $flag_silent | $flags); -- } else { -- open(OLDERR, ">&STDERR"); -- open(STDERR, ">", "/dev/null"); -- $self->{geoip} = Geo::IP->new($flags); -- $self->{geoisp} = Geo::IP->open_type($flag_isp); -- open(STDERR, ">&OLDERR"); -- close(OLDERR); -- } -- }; -- if ($@ || !($self->{geoip} || $self->{geoisp})) { -- $@ =~ s/\s+Trace begun.*//s; -- warn "URILocalBL: GeoIP load failed: $@\n"; -- return 0; -- } -- -- $db_info = sub { return "Geo::IP " . ($self->{geoip}->database_info || '?') }; -- } else { -- dbg("No GeoIP module available"); -- return 0; -- } -- -- my %uri_detail = %{ $permsg->get_uri_detail_list() }; -- my $test = $permsg->{current_rule_name}; -- my $rule = $permsg->{conf}->{uri_local_bl}->{$test}; -- -- my %hit_tests; -- my $got_hit = 0; -- my @addrs; -- my $IP_ADDRESS = IP_ADDRESS; -- -- if ( defined $self->{geoip} ) { -- dbg("check: uri_local_bl evaluating rule %s using database %s\n", $test, $db_info->()); -- } else { -- dbg("check: uri_local_bl evaluating rule %s\n", $test); -- } -- -- my $dns_available = $permsg->is_dns_available(); -- -- while (my ($raw, $info) = each %uri_detail) { -- -- next unless $info->{hosts}; -- -- # look for W3 links only -- next unless (defined $info->{types}->{a} || defined $info->{types}->{parsed}); -- -- while (my($host, $domain) = each %{$info->{hosts}}) { -- -- # skip if the domain name was matched -- if (exists $rule->{exclusions} && exists $rule->{exclusions}->{$domain}) { -- dbg("check: uri_local_bl excludes %s as *.%s\n", $host, $domain); -- next; -- } -- -- if($host !~ /^$IP_ADDRESS$/) { -- if (!$dns_available) { -- dbg("check: uri_local_bl skipping $host, dns not available"); -- next; -- } -- # this would be best cached from prior lookups -- @addrs = gethostbyname($host); -- # convert to string values address list -- @addrs = map { inet_ntoa($_); } @addrs[4..$#addrs]; -- } else { -- @addrs = ($host); -- } -- -- dbg("check: uri_local_bl %s addrs %s\n", $host, join(', ', @addrs)); -- -- for my $ip (@addrs) { -- # skip if the address was matched -- if (exists $rule->{exclusions} && exists $rule->{exclusions}->{$ip}) { -- dbg("check: uri_local_bl excludes %s(%s)\n", $host, $ip); -- next; -- } -- -- if (exists $rule->{countries}) { -- dbg("check: uri_local_bl countries %s\n", join(' ', sort keys %{$rule->{countries}})); -- -- if ( $self->{use_geoip2} == 1 ) { -- my $country; -- if (index($self->{geoip}->metadata()->description()->{en}, 'City') != -1) { -- $country = $self->{geoip}->city( ip => $ip ); -- } else { -- $country = $self->{geoip}->country( ip => $ip ); -- } -- my $country_rec = $country->country(); -- $cc = $country_rec->iso_code(); -- } else { -- $cc = $self->{geoip}->country_code_by_addr($ip); -- } -- -- dbg("check: uri_local_bl host %s(%s) maps to %s\n", $host, $ip, (defined $cc ? $cc : "(undef)")); -- -- # handle there being no associated country (yes, there are holes in -- # the database). -- next unless defined $cc; -- -- # not in blacklist -- next unless (exists $rule->{countries}->{$cc}); -- -- dbg("check: uri_block_cc host %s(%s) matched\n", $host, $ip); -- -- if (would_log('dbg', 'rules') > 1) { -- dbg("check: uri_block_cc criteria for $test met"); -- } -- -- $permsg->test_log("Host: $host in $cc"); -- $hit_tests{$test} = 1; -- -- # reset hash -- keys %uri_detail; -- } -- -- if (exists $rule->{continents}) { -- dbg("check: uri_local_bl continents %s\n", join(' ', sort keys %{$rule->{continents}})); -- -- if ( $self->{use_geoip2} == 1 ) { -- my $country = $self->{geoip}->country( ip => $ip ); -- my $cont_rec = $country->continent(); -- $cont = $cont_rec->{code}; -- } else { -- $cc = $self->{geoip}->country_code_by_addr($ip); -- $cont = $self->{geoip}->continent_code_by_country_code($cc); -- } -- -- dbg("check: uri_local_bl host %s(%s) maps to %s\n", $host, $ip, (defined $cont ? $cont : "(undef)")); -- -- # handle there being no associated continent (yes, there are holes in -- # the database). -- next unless defined $cont; -- -- # not in blacklist -- next unless (exists $rule->{continents}->{$cont}); -- -- dbg("check: uri_block_cont host %s(%s) matched\n", $host, $ip); -- -- if (would_log('dbg', 'rules') > 1) { -- dbg("check: uri_block_cont criteria for $test met"); -- } -- -- $permsg->test_log("Host: $host in $cont"); -- $hit_tests{$test} = 1; -- -- # reset hash -- keys %uri_detail; -- } -- -- if (exists $rule->{isps}) { -- dbg("check: uri_local_bl isps %s\n", join(' ', map { '"' . $_ . '"'; } sort keys %{$rule->{isps}})); -- -- if ( $self->{use_geoip2} == 1 ) { -- $isp = $self->{geoisp}->isp(ip => $ip); -- } else { -- $isp = $self->{geoisp}->isp_by_name($ip); -- } -- -- dbg("check: uri_local_bl isp %s(%s) maps to %s\n", $host, $ip, (defined $isp ? '"' . $isp . '"' : "(undef)")); -- -- # handle there being no associated country -- next unless defined $isp; -- -- # not in blacklist -- next unless (exists $rule->{isps}->{$isp}); -- -- dbg("check: uri_block_isp host %s(%s) matched\n", $host, $ip); -- -- if (would_log('dbg', 'rules') > 1) { -- dbg("check: uri_block_isp criteria for $test met"); -- } -- -- $permsg->test_log("Host: $host in \"$isp\""); -- $hit_tests{$test} = 1; -- -- # reset hash -- keys %uri_detail; -- } -- -- if (exists $rule->{cidr}) { -- dbg("check: uri_block_cidr list %s\n", join(' ', $rule->{cidr}->list_range())); -- -- next unless ($rule->{cidr}->find($ip)); -- -- dbg("check: uri_block_cidr host %s(%s) matched\n", $host, $ip); -- -- if (would_log('dbg', 'rules') > 1) { -- dbg("check: uri_block_cidr criteria for $test met"); -- } -- -- $permsg->test_log("Host: $host as $ip"); -- $hit_tests{$test} = 1; -- -- # reset hash -- keys %uri_detail; -- } -- } -- } -- # cycle through all tests hitted by the uri -- while((my $test_ok) = each %hit_tests) { -- $permsg->got_hit($test_ok); -- $got_hit = 1; -- } -- if($got_hit == 1) { -- return 1; -- } else { -- keys %hit_tests; -- } -- } -- -- dbg("check: uri_local_bl %s no match\n", $test); -- -- return 0; --} -- --1; -- -diff --git a/lib/Mail/SpamAssassin/Util/DependencyInfo.pm b/lib/Mail/SpamAssassin/Util/DependencyInfo.pm -index 2f8aa65..eca12e1 100644 ---- a/lib/Mail/SpamAssassin/Util/DependencyInfo.pm -+++ b/lib/Mail/SpamAssassin/Util/DependencyInfo.pm -@@ -124,46 +124,6 @@ our @OPTIONAL_MODULES = ( - desc => 'Used to check DNS Sender Policy Framework (SPF) records to fight email - address forgery and make it easier to identify spams.', - }, --{ -- module => 'GeoIP2::Database::Reader', -- version => 0, -- desc => 'Used by the RelayCountry plugin (not enabled by default) to -- determine the domain country codes of each relay in the path of an email. -- Also used by the URILocalBL plugin (not enabled by default) to provide ISP -- and Country code based filtering.', --}, --{ -- module => 'Geo::IP', -- version => 0, -- desc => 'Used by the RelayCountry plugin (not enabled by default) to determine -- the domain country codes of each relay in the path of an email. Also used by -- the URILocalBL plugin to provide ISP and Country code based filtering.', --}, --{ -- module => 'IP::Country::DB_File', -- version => 0, -- desc => 'Used by the RelayCountry plugin (not enabled by default) to -- determine the domain country codes of each relay in the path of an email. -- Also used by the URILocalBL plugin (not enabled by default) to provide -- Country code based filtering.', --}, --{ -- module => 'Net::CIDR::Lite', -- version => 0, -- desc => 'Used by the URILocalBL plugin to process IP address ranges.', --}, --{ -- module => 'Razor2::Client::Agent', -- alt_name => 'Razor2', -- version => '2.61', -- desc => 'Used to check message signatures against Vipul\'s Razor collaborative -- filtering network. Razor has a large number of dependencies on CPAN -- modules. Feel free to skip installing it, if this makes you nervous; -- SpamAssassin will still work well without it. -- -- More info on installing and using Razor can be found -- at http://wiki.apache.org/spamassassin/InstallingRazor .', --}, - #{ - # module => 'Net::Ident', - # version => 0, -diff --git a/rules/init.pre b/rules/init.pre -index f9ee06a..0539b29 100644 ---- a/rules/init.pre -+++ b/rules/init.pre -@@ -14,13 +14,6 @@ - # added to new files, named according to the release they're added in. - ########################################################################### - --# RelayCountry - add metadata for Bayes learning, marking the countries --# a message was relayed through --# --# Note: This requires the Geo::IP Perl module --# --# loadplugin Mail::SpamAssassin::Plugin::RelayCountry -- - # URIDNSBL - look up URLs found in the message against several DNS - # blocklists. - # -diff --git a/rules/v341.pre b/rules/v341.pre -index 489dd4c..7ff8e84 100644 ---- a/rules/v341.pre -+++ b/rules/v341.pre -@@ -19,10 +19,5 @@ - # TxRep - Reputation database that replaces AWL - # loadplugin Mail::SpamAssassin::Plugin::TxRep - --# URILocalBL - Provides ISP and Country code based filtering as well as --# quick IP based blocks without a full RBL implementation - Bug 7060 -- --# loadplugin Mail::SpamAssassin::Plugin::URILocalBL -- - # PDFInfo - Use several methods to detect a PDF file's ham/spam traits - # loadplugin Mail::SpamAssassin::Plugin::PDFInfo -diff --git a/spamassassin.raw b/spamassassin.raw -index 4b52ef9..959297a 100755 ---- a/spamassassin.raw -+++ b/spamassassin.raw -@@ -872,9 +872,6 @@ from the SpamAssassin distribution. - Mail::SpamAssassin::Plugin::Hashcash - perform hashcash verification tests - -- Mail::SpamAssassin::Plugin::RelayCountry -- add message metadata indicating the country code of each relay -- - Mail::SpamAssassin::Plugin::SPF - perform SPF verification tests - diff --git a/SOURCES/spamassassin-3.4.6-Drop-the-ResourceLimits-plugin.patch b/SOURCES/spamassassin-3.4.6-Drop-the-ResourceLimits-plugin.patch new file mode 100644 index 0000000..6cad38a --- /dev/null +++ b/SOURCES/spamassassin-3.4.6-Drop-the-ResourceLimits-plugin.patch @@ -0,0 +1,193 @@ +diff --git a/MANIFEST b/MANIFEST +index e16e0da..601f886 100644 +--- a/MANIFEST ++++ b/MANIFEST +@@ -101,7 +101,6 @@ lib/Mail/SpamAssassin/Plugin/Pyzor.pm + lib/Mail/SpamAssassin/Plugin/Razor2.pm + lib/Mail/SpamAssassin/Plugin/RelayCountry.pm + lib/Mail/SpamAssassin/Plugin/RelayEval.pm +-lib/Mail/SpamAssassin/Plugin/ResourceLimits.pm + lib/Mail/SpamAssassin/Plugin/ReplaceTags.pm + lib/Mail/SpamAssassin/Plugin/Reuse.pm + lib/Mail/SpamAssassin/Plugin/Rule2XSBody.pm +diff --git a/lib/Mail/SpamAssassin/Plugin/ResourceLimits.pm b/lib/Mail/SpamAssassin/Plugin/ResourceLimits.pm +deleted file mode 100644 +index 9179b93..0000000 +--- a/lib/Mail/SpamAssassin/Plugin/ResourceLimits.pm ++++ /dev/null +@@ -1,143 +0,0 @@ +-# <@LICENSE> +-# Licensed to the Apache Software Foundation (ASF) under one or more +-# contributor license agreements. See the NOTICE file distributed with +-# this work for additional information regarding copyright ownership. +-# The ASF licenses this file to you under the Apache License, Version 2.0 +-# (the "License"); you may not use this file except in compliance with +-# the License. You may obtain a copy of the License at: +-# +-# http://www.apache.org/licenses/LICENSE-2.0 +-# +-# Unless required by applicable law or agreed to in writing, software +-# distributed under the License is distributed on an "AS IS" BASIS, +-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-# See the License for the specific language governing permissions and +-# limitations under the License. +-# +- +-=head1 NAME +- +-Mail::SpamAssassin::Plugin::ResourceLimits - Limit the memory and/or CPU of child spamd processes +- +-=head1 SYNOPSIS +- +- # This plugin is for admin only and cannot be specified in user config. +- loadplugin Mail::SpamAssassin::Plugin::ResourceLimits +- +- # Sets to RLIMIT_CPU from BSD::Resource. The quota is based on max CPU Time seconds. +- resource_limit_cpu 120 +- +- # Sets to RLIMIT_RSS and RLIMIT_AS via BSD::Resource. +- resource_limit_cpu 536870912 +- +-=head1 DESCRIPTION +- +-This module leverages BSD::Resource to assure your spamd child processes do not exceed +-specified CPU or memory limit. If this happens, the child process will die. +-See the L for more details. +- +-NOTE: Because this plugin uses BSD::Resource, it will not function on Windows. +- +-=head1 ADMINISTRATOR SETTINGS +- +-=over 4 +- +-=item resource_limit_cpu 120 (default: 0 or no limit) +- +-How many cpu cycles are allowed on this process before it dies. +- +-=item resource_limit_mem 536870912 (default: 0 or no limit) +- +-The maximum number of bytes of memory allowed both for: +- +-=over +- +-=item * +- +-(virtual) address space bytes +- +-=item * +- +-resident set size +- +-=back +- +-=back +- +-=cut +- +-package Mail::SpamAssassin::Plugin::ResourceLimits; +- +-use Mail::SpamAssassin::Plugin (); +-use Mail::SpamAssassin::Logger (); +-use Mail::SpamAssassin::Util (); +-use Mail::SpamAssassin::Constants qw(:sa); +- +-use strict; +-use warnings; +- +-use BSD::Resource qw(RLIMIT_RSS RLIMIT_AS RLIMIT_CPU); +- +-our @ISA = qw(Mail::SpamAssassin::Plugin); +- +-sub new { +- my $class = shift; +- my $mailsaobject = shift; +- +- $class = ref($class) || $class; +- my $self = $class->SUPER::new($mailsaobject); +- bless( $self, $class ); +- +- $self->set_config( $mailsaobject->{conf} ); +- return $self; +-} +- +-sub set_config { +- my ( $self, $conf ) = @_; +- my @cmds = (); +- +- push( +- @cmds, +- { +- setting => 'resource_limit_mem', +- is_admin => 1, +- default => '0', +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC +- } +- ); +- +- push( +- @cmds, +- { +- setting => 'resource_limit_cpu', +- is_admin => 1, +- default => '0', +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC +- } +- ); +- +- $conf->{parser}->register_commands( \@cmds ); +-} +- +-sub spamd_child_init { +- my ($self) = @_; +- +- # Set CPU Resource limits if they were specified. +- Mail::SpamAssassin::Util::dbg("resourcelimitplugin: In spamd_child_init"); +- Mail::SpamAssassin::Util::dbg( "resourcelimitplugin: cpu limit: " . $self->{main}->{conf}->{resource_limit_cpu} ); +- if ( $self->{main}->{conf}->{resource_limit_cpu} ) { +- BSD::Resource::setrlimit( RLIMIT_CPU, $self->{main}->{conf}->{resource_limit_cpu}, $self->{main}->{conf}->{resource_limit_cpu} ) +- || info("resourcelimitplugin: Unable to set RLIMIT_CPU"); +- } +- +- # Set Resource limits if they were specified. +- Mail::SpamAssassin::Util::dbg( "resourcelimitplugin: mem limit: " . $self->{main}->{conf}->{resource_limit_mem} ); +- if ( $self->{main}->{conf}->{resource_limit_mem} ) { +- BSD::Resource::setrlimit( RLIMIT_RSS, $self->{main}->{conf}->{resource_limit_mem}, $self->{main}->{conf}->{resource_limit_mem} ) +- || info("resourcelimitplugin: Unable to set RLIMIT_RSS"); +- BSD::Resource::setrlimit( RLIMIT_AS, $self->{main}->{conf}->{resource_limit_mem}, $self->{main}->{conf}->{resource_limit_mem} ) +- || info("resourcelimitplugin: Unable to set RLIMIT_AS"); +- } +-} +- +-1; +diff --git a/lib/Mail/SpamAssassin/Util/DependencyInfo.pm b/lib/Mail/SpamAssassin/Util/DependencyInfo.pm +index b5b05cf..8223b26 100644 +--- a/lib/Mail/SpamAssassin/Util/DependencyInfo.pm ++++ b/lib/Mail/SpamAssassin/Util/DependencyInfo.pm +@@ -234,12 +234,6 @@ our @OPTIONAL_MODULES = ( + check for both Net::DNS and Net::DNS::Nameserver. However, + Net::DNS::Nameserver is only used in make test as of June 2014.', + }, +-{ +- module => 'BSD::Resource', +- version => 0, +- desc => 'BSD::Resource provides BSD process resource limit and priority +- functions. It is used by the optional ResourceLimits Plugin.', +-}, + { + module => 'Archive::Zip', + version => 0, +diff --git a/rules/v342.pre b/rules/v342.pre +index 8e0fb07..c4758e9 100644 +--- a/rules/v342.pre ++++ b/rules/v342.pre +@@ -19,10 +19,6 @@ + # HashBL - Query hashed/unhashed strings, emails, uris etc from DNS lists + # loadplugin Mail::SpamAssassin::Plugin::HashBL + +-# ResourceLimits - assure your spamd child processes +-# do not exceed specified CPU or memory limit +-# loadplugin Mail::SpamAssassin::Plugin::ResourceLimits +- + # FromNameSpoof - help stop spam that tries to spoof other domains using + # the from name + # loadplugin Mail::SpamAssassin::Plugin::FromNameSpoof diff --git a/SOURCES/spamassassin-3.4.6-drop-geoip.patch b/SOURCES/spamassassin-3.4.6-drop-geoip.patch new file mode 100644 index 0000000..0710408 --- /dev/null +++ b/SOURCES/spamassassin-3.4.6-drop-geoip.patch @@ -0,0 +1,1234 @@ +diff --git a/MANIFEST b/MANIFEST +index 7b1bab2..e16e0da 100644 +--- a/MANIFEST ++++ b/MANIFEST +@@ -118,7 +118,6 @@ lib/Mail/SpamAssassin/Plugin/VBounce.pm + lib/Mail/SpamAssassin/Plugin/WLBLEval.pm + lib/Mail/SpamAssassin/Plugin/WhiteListSubject.pm + lib/Mail/SpamAssassin/PluginHandler.pm +-lib/Mail/SpamAssassin/Plugin/URILocalBL.pm + lib/Mail/SpamAssassin/RegistryBoundaries.pm + lib/Mail/SpamAssassin/Reporter.pm + lib/Mail/SpamAssassin/SQLBasedAddrList.pm +diff --git a/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm b/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm +deleted file mode 100644 +index 38ec1e3..0000000 +--- a/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm ++++ /dev/null +@@ -1,407 +0,0 @@ +-# <@LICENSE> +-# Licensed to the Apache Software Foundation (ASF) under one or more +-# contributor license agreements. See the NOTICE file distributed with +-# this work for additional information regarding copyright ownership. +-# The ASF licenses this file to you under the Apache License, Version 2.0 +-# (the "License"); you may not use this file except in compliance with +-# the License. You may obtain a copy of the License at: +-# +-# http://www.apache.org/licenses/LICENSE-2.0 +-# +-# Unless required by applicable law or agreed to in writing, software +-# distributed under the License is distributed on an "AS IS" BASIS, +-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-# See the License for the specific language governing permissions and +-# limitations under the License. +-# +- +-=head1 NAME +- +-RelayCountry - add message metadata indicating the country code of each relay +- +-=head1 SYNOPSIS +- +- loadplugin Mail::SpamAssassin::Plugin::RelayCountry +- +-=head1 DESCRIPTION +- +-The RelayCountry plugin attempts to determine the domain country codes +-of each relay used in the delivery path of messages and add that information +-to the message metadata. +- +-Following metadata headers and tags are added: +- +- X-Relay-Countries _RELAYCOUNTRY_ +- All untrusted relays. Contains all relays starting from the +- trusted_networks border. This method has been used by default since +- early SA versions. +- +- X-Relay-Countries-External _RELAYCOUNTRYEXT_ +- All external relays. Contains all relays starting from the +- internal_networks border. Could be useful in some cases when +- trusted/msa_networks extend beyond the internal border and those +- need to be checked too. +- +- X-Relay-Countries-All _RELAYCOUNTRYALL_ +- All possible relays (internal + external). +- +- X-Relay-Countries-Auth _RELAYCOUNTRYAUTH_ +- Auth will contain all relays starting from the first relay that used +- authentication. For example, this could be used to check for hacked +- local users coming in from unexpected countries. If there are no +- authenticated relays, this will be empty. +- +-=head1 REQUIREMENT +- +-This plugin requires the GeoIP2, Geo::IP, IP::Country::DB_File or +-IP::Country::Fast module from CPAN. +-For backward compatibility IP::Country::Fast is used as fallback if no db_type +-is specified in the config file. +- +-=cut +- +-package Mail::SpamAssassin::Plugin::RelayCountry; +- +-use Mail::SpamAssassin::Plugin; +-use Mail::SpamAssassin::Logger; +-use Mail::SpamAssassin::Constants qw(:ip); +-use strict; +-use warnings; +-# use bytes; +-use re 'taint'; +- +-our @ISA = qw(Mail::SpamAssassin::Plugin); +- +-# constructor: register the eval rule +-sub new { +- my $class = shift; +- my $mailsaobject = shift; +- +- # some boilerplate... +- $class = ref($class) || $class; +- my $self = $class->SUPER::new($mailsaobject); +- bless ($self, $class); +- +- $self->set_config($mailsaobject->{conf}); +- return $self; +-} +- +-sub set_config { +- my ($self, $conf) = @_; +- my @cmds; +- +-=head1 USER PREFERENCES +- +-The following options can be used in both site-wide (C) and +-user-specific (C) configuration files to customize how +-SpamAssassin handles incoming email messages. +- +-=over 4 +- +-=item country_db_type STRING +- +-This option tells SpamAssassin which type of Geo database to use. +-Valid database types are GeoIP, GeoIP2, DB_File and Fast. +- +-=back +- +-=cut +- +- push (@cmds, { +- setting => 'country_db_type', +- default => "GeoIP", +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- if ($value !~ /^(?:GeoIP|GeoIP2|DB_File|Fast)$/) { +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- $self->{country_db_type} = $value; +- } +- }); +- +-=over 4 +- +-=item country_db_path STRING +- +-This option tells SpamAssassin where to find MaxMind GeoIP2 or IP::Country::DB_File database. +- +-If not defined, GeoIP2 default search includes: +- /usr/local/share/GeoIP/GeoIP2-Country.mmdb +- /usr/share/GeoIP/GeoIP2-Country.mmdb +- /var/lib/GeoIP/GeoIP2-Country.mmdb +- /usr/local/share/GeoIP/GeoLite2-Country.mmdb +- /usr/share/GeoIP/GeoLite2-Country.mmdb +- /var/lib/GeoIP/GeoLite2-Country.mmdb +- (and same paths again for -City.mmdb, which also has country functionality) +- +-=back +- +-=cut +- +- push (@cmds, { +- setting => 'country_db_path', +- default => "", +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- if (!defined $value || !length $value) { +- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; +- } +- if (!-e $value) { +- info("config: country_db_path \"$value\" is not accessible"); +- $self->{country_db_path} = $value; +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- $self->{country_db_path} = $value; +- } +- }); +- +- push (@cmds, { +- setting => 'geoip2_default_db_path', +- default => [ +- '/usr/local/share/GeoIP/GeoIP2-Country.mmdb', +- '/usr/share/GeoIP/GeoIP2-Country.mmdb', +- '/var/lib/GeoIP/GeoIP2-Country.mmdb', +- '/usr/local/share/GeoIP/GeoLite2-Country.mmdb', +- '/usr/share/GeoIP/GeoLite2-Country.mmdb', +- '/var/lib/GeoIP/GeoLite2-Country.mmdb', +- '/usr/local/share/GeoIP/GeoIP2-City.mmdb', +- '/usr/share/GeoIP/GeoIP2-City.mmdb', +- '/var/lib/GeoIP/GeoIP2-City.mmdb', +- '/usr/local/share/GeoIP/GeoLite2-City.mmdb', +- '/usr/share/GeoIP/GeoLite2-City.mmdb', +- '/var/lib/GeoIP/GeoLite2-City.mmdb', +- ], +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRINGLIST, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- if ($value eq '') { +- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; +- } +- push(@{$self->{geoip2_default_db_path}}, split(/\s+/, $value)); +- } +- }); +- +- $conf->{parser}->register_commands(\@cmds); +-} +- +-sub get_country { +- my ($self, $ip, $db, $dbv6, $country_db_type) = @_; +- my $cc; +- my $IP_PRIVATE = IP_PRIVATE; +- my $IPV4_ADDRESS = IPV4_ADDRESS; +- +- # Private IPs will always be returned as '**' +- if ($ip =~ /^$IP_PRIVATE$/o) { +- $cc = "**"; +- } +- elsif ($country_db_type eq "GeoIP") { +- if ($ip =~ /^$IPV4_ADDRESS$/o) { +- $cc = $db->country_code_by_addr($ip); +- } elsif (defined $dbv6) { +- $cc = $dbv6->country_code_by_addr_v6($ip); +- } +- } +- elsif ($country_db_type eq "GeoIP2") { +- my ($country, $country_rec); +- eval { +- if (index($db->metadata()->description()->{en}, 'City') != -1) { +- $country = $db->city( ip => $ip ); +- } else { +- $country = $db->country( ip => $ip ); +- } +- $country_rec = $country->country(); +- $cc = $country_rec->iso_code(); +- 1; +- } or do { +- $@ =~ s/\s+Trace begun.*//s; +- dbg("metadata: RelayCountry: GeoIP2 failed: $@"); +- } +- } +- elsif ($country_db_type eq "DB_File") { +- if ($ip =~ /^$IPV4_ADDRESS$/o ) { +- $cc = $db->inet_atocc($ip); +- } else { +- $cc = $db->inet6_atocc($ip); +- } +- } +- elsif ($country_db_type eq "Fast") { +- $cc = $db->inet_atocc($ip); +- } +- +- $cc ||= 'XX'; +- +- return $cc; +-} +- +-sub extract_metadata { +- my ($self, $opts) = @_; +- my $pms = $opts->{permsgstatus}; +- +- my $db; +- my $dbv6; +- my $db_info; # will hold database info +- my $db_type; # will hold database type +- +- my $country_db_type = $opts->{conf}->{country_db_type}; +- my $country_db_path = $opts->{conf}->{country_db_path}; +- +- if ($country_db_type eq "GeoIP") { +- eval { +- require Geo::IP; +- $db = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION, Geo::IP->GEOIP_STANDARD); +- die "GeoIP.dat not found" unless $db; +- # IPv6 requires version Geo::IP 1.39+ with GeoIP C API 1.4.7+ +- if (Geo::IP->VERSION >= 1.39 && Geo::IP->api eq 'CAPI') { +- $dbv6 = Geo::IP->open_type(Geo::IP->GEOIP_COUNTRY_EDITION_V6, Geo::IP->GEOIP_STANDARD); +- if (!$dbv6) { +- dbg("metadata: RelayCountry: GeoIP: IPv6 support not enabled, GeoIPv6.dat not found"); +- } +- } else { +- dbg("metadata: RelayCountry: GeoIP: IPv6 support not enabled, versions Geo::IP 1.39, GeoIP C API 1.4.7 required"); +- } +- $db_info = sub { return "Geo::IP IPv4: " . ($db->database_info || '?')." / IPv6: ".($dbv6 ? $dbv6->database_info || '?' : '?') }; +- 1; +- } or do { +- # Fallback to IP::Country::Fast +- dbg("metadata: RelayCountry: GeoIP: GeoIP.dat not found, trying IP::Country::Fast as fallback"); +- $country_db_type = "Fast"; +- } +- } +- elsif ($country_db_type eq "GeoIP2") { +- if (!$country_db_path) { +- # Try some default locations +- foreach (@{$opts->{conf}->{geoip2_default_db_path}}) { +- if (-f $_) { +- $country_db_path = $_; +- last; +- } +- } +- } +- if (-f $country_db_path) { +- eval { +- require GeoIP2::Database::Reader; +- $db = GeoIP2::Database::Reader->new( +- file => $country_db_path, +- locales => [ 'en' ] +- ); +- die "unknown error" unless $db; +- $db_info = sub { +- my $m = $db->metadata(); +- return "GeoIP2 ".$m->description()->{en}." / ".localtime($m->build_epoch()); +- }; +- 1; +- } or do { +- # Fallback to IP::Country::Fast +- $@ =~ s/\s+Trace begun.*//s; +- dbg("metadata: RelayCountry: GeoIP2: ${country_db_path} load failed: $@, trying IP::Country::Fast as fallback"); +- $country_db_type = "Fast"; +- } +- } else { +- # Fallback to IP::Country::Fast +- my $err = $country_db_path ? +- "$country_db_path not found" : "database not found from default locations"; +- dbg("metadata: RelayCountry: GeoIP2: $err, trying IP::Country::Fast as fallback"); +- $country_db_type = "Fast"; +- } +- } +- elsif ($country_db_type eq "DB_File") { +- if (-f $country_db_path) { +- eval { +- require IP::Country::DB_File; +- $db = IP::Country::DB_File->new($country_db_path); +- die "unknown error" unless $db; +- $db_info = sub { return "IP::Country::DB_File ".localtime($db->db_time()); }; +- 1; +- } or do { +- # Fallback to IP::Country::Fast +- dbg("metadata: RelayCountry: DB_File: ${country_db_path} load failed: $@, trying IP::Country::Fast as fallback"); +- $country_db_type = "Fast"; +- } +- } else { +- # Fallback to IP::Country::Fast +- dbg("metadata: RelayCountry: DB_File: ${country_db_path} not found, trying IP::Country::Fast as fallback"); +- $country_db_type = "Fast"; +- } +- } +- +- if ($country_db_type eq "Fast") { +- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat; +- eval { +- require IP::Country::Fast; +- $db = IP::Country::Fast->new(); +- $db_info = sub { return "IP::Country::Fast ".localtime($db->db_time()); }; +- 1; +- } or do { +- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat; +- dbg("metadata: RelayCountry: failed to load 'IP::Country::Fast', skipping: $eval_stat"); +- return 1; +- } +- } +- +- if (!$db) { +- return 1; +- } +- +- dbg("metadata: RelayCountry: Using database: ".$db_info->()); +- my $msg = $opts->{msg}; +- +- my @cc_untrusted; +- foreach my $relay (@{$msg->{metadata}->{relays_untrusted}}) { +- my $ip = $relay->{ip}; +- my $cc = $self->get_country($ip, $db, $dbv6, $country_db_type); +- push @cc_untrusted, $cc; +- } +- +- my @cc_external; +- foreach my $relay (@{$msg->{metadata}->{relays_external}}) { +- my $ip = $relay->{ip}; +- my $cc = $self->get_country($ip, $db, $dbv6, $country_db_type); +- push @cc_external, $cc; +- } +- +- my @cc_auth; +- my $found_auth; +- foreach my $relay (@{$msg->{metadata}->{relays_trusted}}) { +- if ($relay->{auth}) { +- $found_auth = 1; +- } +- if ($found_auth) { +- my $ip = $relay->{ip}; +- my $cc = $self->get_country($ip, $db, $dbv6, $country_db_type); +- push @cc_auth, $cc; +- } +- } +- +- my @cc_all; +- foreach my $relay (@{$msg->{metadata}->{relays_internal}}, @{$msg->{metadata}->{relays_external}}) { +- my $ip = $relay->{ip}; +- my $cc = $self->get_country($ip, $db, $dbv6, $country_db_type); +- push @cc_all, $cc; +- } +- +- my $ccstr = join(' ', @cc_untrusted); +- $msg->put_metadata("X-Relay-Countries", $ccstr); +- dbg("metadata: X-Relay-Countries: $ccstr"); +- $pms->set_tag("RELAYCOUNTRY", @cc_untrusted == 1 ? $cc_untrusted[0] : \@cc_untrusted); +- +- $ccstr = join(' ', @cc_external); +- $msg->put_metadata("X-Relay-Countries-External", $ccstr); +- dbg("metadata: X-Relay-Countries-External: $ccstr"); +- $pms->set_tag("RELAYCOUNTRYEXT", @cc_external == 1 ? $cc_external[0] : \@cc_external); +- +- $ccstr = join(' ', @cc_auth); +- $msg->put_metadata("X-Relay-Countries-Auth", $ccstr); +- dbg("metadata: X-Relay-Countries-Auth: $ccstr"); +- $pms->set_tag("RELAYCOUNTRYAUTH", @cc_auth == 1 ? $cc_auth[0] : \@cc_auth); +- +- $ccstr = join(' ', @cc_all); +- $msg->put_metadata("X-Relay-Countries-All", $ccstr); +- dbg("metadata: X-Relay-Countries-All: $ccstr"); +- $pms->set_tag("RELAYCOUNTRYALL", @cc_all == 1 ? $cc_all[0] : \@cc_all); +- +- return 1; +-} +- +-1; +diff --git a/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm b/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm +deleted file mode 100644 +index 4def393..0000000 +--- a/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm ++++ /dev/null +@@ -1,705 +0,0 @@ +-# <@LICENSE> +-# Licensed to the Apache Software Foundation (ASF) under one or more +-# contributor license agreements. See the NOTICE file distributed with +-# this work for additional information regarding copyright ownership. +-# The ASF licenses this file to you under the Apache License, Version 2.0 +-# (the "License"); you may not use this file except in compliance with +-# the License. You may obtain a copy of the License at: +-# +-# http://www.apache.org/licenses/LICENSE-2.0 +-# +-# Unless required by applicable law or agreed to in writing, software +-# distributed under the License is distributed on an "AS IS" BASIS, +-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-# See the License for the specific language governing permissions and +-# limitations under the License. +-# +- +-=head1 NAME +- +-URILocalBL - blacklist URIs using local information (ISP names, address lists, and country codes) +- +-=head1 SYNOPSIS +- +-This plugin creates some new rule test types, such as "uri_block_cc", +-"uri_block_cidr", and "uri_block_isp". These rules apply to the URIs +-found in the HTML portion of a message, i.e. markup. +- +- loadplugin Mail::SpamAssassin::Plugin::URILocalBL +- +-Why local blacklisting? There are a few excellent, effective, and +-well-maintained DNSBL's out there. But they have several drawbacks: +- +-=over 2 +- +-=item * blacklists can cover tens of thousands of entries, and you can't select which ones you use; +- +-=item * verifying that it's correctly configured can be non-trivial; +- +-=item * new blacklisting entries may take a while to be detected and entered, so it's not instantaneous. +- +-=back +- +-Sometimes all you want is a quick, easy, and very surgical blacklisting of +-a particular site or a particular ISP. This plugin is defined for that +-exact usage case. +- +-=head1 RULE DEFINITIONS AND PRIVILEGED SETTINGS +- +-The format for defining a rule is as follows: +- +- uri_block_cc SYMBOLIC_TEST_NAME cc1 cc2 cc3 cc4 +- +-or: +- +- uri_block_cont SYMBOLIC_TEST_NAME co1 co2 co3 co4 +- +-or: +- +- uri_block_cidr SYMBOLIC_TEST_NAME a.a.a.a b.b.b.b/cc d.d.d.d-e.e.e.e +- +-or: +- +- uri_block_isp SYMBOLIC_TEST_NAME "DataRancid" "McCarrier" "Phishers-r-Us" +- +-Example rule for matching a URI in China: +- +- uri_block_cc TEST1 cn +- +-This would block the URL http://www.baidu.com/index.htm. Similarly, to +-match a Spam-haven netblock: +- +- uri_block_cidr TEST2 65.181.64.0/18 +- +-would match a netblock where several phishing sites were recently hosted. +- +-And to block all CIDR blocks registered to an ISP, one might use: +- +- uri_block_isp TEST3 "ColoCrossing" +- +-if one didn't trust URL's pointing to that organization's clients. Lastly, +-if there's a country that you want to block but there's an explicit host +-you wish to exempt from that blacklist, you can use: +- +- uri_block_exclude TEST1 www.baidu.com +- +-if you wish to exempt URL's referring to this host. The same syntax is +-applicable to CIDR and ISP blocks as well. +- +-=head1 DEPENDENCIES +- +-The Country-Code based filtering requires the Geo::IP or GeoIP2 module, +-which uses either the fremium GeoLiteCountry database, or the commercial +-version of it called GeoIP from MaxMind.com. +- +-The ISP based filtering requires the same module, plus the GeoIPISP database. +-There is no fremium version of this database, so commercial licensing is +-required. +- +-=cut +- +-package Mail::SpamAssassin::Plugin::URILocalBL; +-use Mail::SpamAssassin::Plugin; +-use Mail::SpamAssassin::Logger; +-use Mail::SpamAssassin::Constants qw(:ip); +-use Mail::SpamAssassin::Util qw(untaint_var); +- +-use Socket; +- +-use strict; +-use warnings; +-# use bytes; +-use re 'taint'; +-use version; +- +-our @ISA = qw(Mail::SpamAssassin::Plugin); +- +-use constant HAS_GEOIP => eval { require Geo::IP; }; +-use constant HAS_GEOIP2 => eval { require GeoIP2::Database::Reader; }; +-use constant HAS_CIDR => eval { require Net::CIDR::Lite; }; +- +-# constructor +-sub new { +- my $class = shift; +- my $mailsaobject = shift; +- +- # some boilerplate... +- $class = ref($class) || $class; +- my $self = $class->SUPER::new($mailsaobject); +- bless ($self, $class); +- +- # how to handle failure to get the database handle? +- # and we don't really have a valid return value... +- # can we defer getting this handle until we actually see +- # a uri_block_cc rule? +- +- $self->register_eval_rule("check_uri_local_bl"); +- +- $self->set_config($mailsaobject->{conf}); +- +- return $self; +-} +- +-sub set_config { +- my ($self, $conf) = @_; +- my @cmds; +- +- my $pluginobj = $self; # allow use inside the closure below +- +- push (@cmds, { +- setting => 'uri_block_cc', +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, +- is_priv => 1, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- +- if ($value !~ /^(\S+)\s+(.+)$/) { +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- my $name = $1; +- my $def = $2; +- my $added_criteria = 0; +- +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{countries} = {}; +- +- # this should match all country codes including satellite providers +- while ($def =~ m/^\s*([a-z][a-z0-9])(\s+(.*)|)$/) { +- my $cc = $1; +- my $rest = $2; +- +- #dbg("config: uri_block_cc adding %s to %s\n", $cc, $name); +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{countries}->{uc($cc)} = 1; +- $added_criteria = 1; +- +- $def = $rest; +- } +- +- if ($added_criteria == 0) { +- warn "config: no arguments"; +- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; +- } elsif ($def ne '') { +- warn "config: failed to add invalid rule $name"; +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- +- dbg("config: uri_block_cc added %s\n", $name); +- +- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); +- } +- }); +- +- push (@cmds, { +- setting => 'uri_block_cont', +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, +- is_priv => 1, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- +- if ($value !~ /^(\S+)\s+(.+)$/) { +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- my $name = $1; +- my $def = $2; +- my $added_criteria = 0; +- +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{continents} = {}; +- +- # this should match all continent codes +- while ($def =~ m/^\s*([a-z]{2})(\s+(.*)|)$/) { +- my $cont = $1; +- my $rest = $2; +- +- # dbg("config: uri_block_cont adding %s to %s\n", $cont, $name); +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{continents}->{uc($cont)} = 1; +- $added_criteria = 1; +- +- $def = $rest; +- } +- +- if ($added_criteria == 0) { +- warn "config: no arguments"; +- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; +- } elsif ($def ne '') { +- warn "config: failed to add invalid rule $name"; +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- +- dbg("config: uri_block_cont added %s\n", $name); +- +- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); +- } +- }); +- +- push (@cmds, { +- setting => 'uri_block_isp', +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, +- is_priv => 1, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- +- if ($value !~ /^(\S+)\s+(.+)$/) { +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- my $name = $1; +- my $def = $2; +- my $added_criteria = 0; +- +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{isps} = {}; +- +- # gather up quoted strings +- while ($def =~ m/^\s*"([^"]*)"(\s+(.*)|)$/) { +- my $isp = $1; +- my $rest = $2; +- +- dbg("config: uri_block_isp adding \"%s\" to %s\n", $isp, $name); +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{isps}->{$isp} = 1; +- $added_criteria = 1; +- +- $def = $rest; +- } +- +- if ($added_criteria == 0) { +- warn "config: no arguments"; +- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; +- } elsif ($def ne '') { +- warn "config: failed to add invalid rule $name"; +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- +- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); +- } +- }); +- +- push (@cmds, { +- setting => 'uri_block_cidr', +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, +- is_priv => 1, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- +- if (!HAS_CIDR) { +- warn "config: uri_block_cidr not supported, required module Net::CIDR::Lite missing\n"; +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- +- if ($value !~ /^(\S+)\s+(.+)$/) { +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- my $name = $1; +- my $def = $2; +- my $added_criteria = 0; +- +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{cidr} = new Net::CIDR::Lite; +- +- # match individual IP's, subnets, and ranges +- while ($def =~ m/^\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2}|-\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?)(\s+(.*)|)$/) { +- my $addr = $1; +- my $rest = $3; +- +- dbg("config: uri_block_cidr adding %s to %s\n", $addr, $name); +- +- eval { $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{cidr}->add_any($addr) }; +- last if ($@); +- +- $added_criteria = 1; +- +- $def = $rest; +- } +- +- if ($added_criteria == 0) { +- warn "config: no arguments"; +- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; +- } elsif ($def ne '') { +- warn "config: failed to add invalid rule $name"; +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- +- # optimize the ranges +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{cidr}->clean(); +- +- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); +- } +- }); +- +- push (@cmds, { +- setting => 'uri_block_exclude', +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE, +- is_priv => 1, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- +- if ($value !~ /^(\S+)\s+(.+)$/) { +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- my $name = $1; +- my $def = $2; +- my $added_criteria = 0; +- +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{exclusions} = {}; +- +- # match individual IP's, or domain names +- while ($def =~ m/^\s*((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(([a-z0-9][-a-z0-9]*[a-z0-9](\.[a-z0-9][-a-z0-9]*[a-z0-9]){1,})))(\s+(.*)|)$/) { +- my $addr = $1; +- my $rest = $6; +- +- dbg("config: uri_block_exclude adding %s to %s\n", $addr, $name); +- +- $conf->{parser}->{conf}->{uri_local_bl}->{$name}->{exclusions}->{$addr} = 1; +- +- $added_criteria = 1; +- +- $def = $rest; +- } +- +- if ($added_criteria == 0) { +- warn "config: no arguments"; +- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; +- } elsif ($def ne '') { +- warn "config: failed to add invalid rule $name"; +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- +- $conf->{parser}->add_test($name, 'check_uri_local_bl()', $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS); +- } +- }); +- +-=over 2 +- +-=item uri_country_db_path STRING +- +-This option tells SpamAssassin where to find the MaxMind country GeoIP2 +-database. Country or City database are both supported. +- +-=back +- +-=cut +- +- push (@cmds, { +- setting => 'uri_country_db_path', +- is_priv => 1, +- default => undef, +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- if (!defined $value || !length $value) { +- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; +- } +- if (!-f $value) { +- info("config: uri_country_db_path \"$value\" is not accessible"); +- $self->{uri_country_db_path} = $value; +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- +- $self->{uri_country_db_path} = $value; +- } +- }); +- +-=over 2 +- +-=item uri_country_db_isp_path STRING +- +-This option tells SpamAssassin where to find the MaxMind isp GeoIP2 database. +- +-=back +- +-=cut +- +- push (@cmds, { +- setting => 'uri_country_db_isp_path', +- is_priv => 1, +- default => undef, +- type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, +- code => sub { +- my ($self, $key, $value, $line) = @_; +- if (!defined $value || !length $value) { +- return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; +- } +- if (!-f $value) { +- info("config: uri_country_db_isp_path \"$value\" is not accessible"); +- $self->{uri_country_db_isp_path} = $value; +- return $Mail::SpamAssassin::Conf::INVALID_VALUE; +- } +- +- $self->{uri_country_db_isp_path} = $value; +- } +- }); +- +- $conf->{parser}->register_commands(\@cmds); +-} +- +-sub check_uri_local_bl { +- my ($self, $permsg) = @_; +- +- my $cc; +- my $cont; +- my $db_info; +- my $isp; +- +- my $conf_country_db_path = $self->{'main'}{'resolver'}{'conf'}->{uri_country_db_path}; +- my $conf_country_db_isp_path = $self->{'main'}{'resolver'}{'conf'}->{uri_country_db_isp_path}; +- # If country_db_path is set I am using GeoIP2 api +- if ( HAS_GEOIP2 and ( ( defined $conf_country_db_path ) or ( defined $conf_country_db_isp_path ) ) ) { +- +- eval { +- $self->{geoip} = GeoIP2::Database::Reader->new( +- file => $conf_country_db_path, +- locales => [ 'en' ] +- ) if (( defined $conf_country_db_path ) && ( -f $conf_country_db_path)); +- if ( defined ($conf_country_db_path) ) { +- $db_info = sub { return "GeoIP2 " . ($self->{geoip}->metadata()->description()->{en} || '?') }; +- warn "$conf_country_db_path not found" unless $self->{geoip}; +- } +- +- $self->{geoisp} = GeoIP2::Database::Reader->new( +- file => $conf_country_db_isp_path, +- locales => [ 'en' ] +- ) if (( defined $conf_country_db_isp_path ) && ( -f $conf_country_db_isp_path)); +- if ( defined ($conf_country_db_isp_path) ) { +- warn "$conf_country_db_isp_path not found" unless $self->{geoisp}; +- } +- $self->{use_geoip2} = 1; +- }; +- if ($@ || !($self->{geoip} || $self->{geoisp})) { +- $@ =~ s/\s+Trace begun.*//s; +- warn "URILocalBL: GeoIP2 load failed: $@\n"; +- return 0; +- } +- +- } elsif ( HAS_GEOIP ) { +- BEGIN { +- Geo::IP->import( qw(GEOIP_MEMORY_CACHE GEOIP_CHECK_CACHE GEOIP_ISP_EDITION) ); +- } +- $self->{use_geoip2} = 0; +- # need GeoIP C library 1.6.3 and GeoIP perl API 1.4.4 or later to avoid messages leaking - Bug 7153 +- my $gic_wanted = version->parse('v1.6.3'); +- my $gic_have = version->parse(Geo::IP->lib_version()); +- my $gip_wanted = version->parse('v1.4.4'); +- my $gip_have = version->parse($Geo::IP::VERSION); +- +- # this code burps an ugly message if it fails, but that's redirected elsewhere +- my $flags = 0; +- my $flag_isp = 0; +- my $flag_silent = 0; +- eval '$flags = GEOIP_MEMORY_CACHE | GEOIP_CHECK_CACHE' if ($gip_have >= $gip_wanted); +- eval '$flag_silent = GEOIP_SILENCE' if ($gip_have >= $gip_wanted); +- eval '$flag_isp = GEOIP_ISP_EDITION' if ($gip_have >= $gip_wanted); +- +- eval { +- if ($flag_silent && $gic_have >= $gic_wanted) { +- $self->{geoip} = Geo::IP->new($flags | $flag_silent); +- $self->{geoisp} = Geo::IP->open_type($flag_isp, $flag_silent | $flags); +- } else { +- open(OLDERR, ">&STDERR"); +- open(STDERR, ">", "/dev/null"); +- $self->{geoip} = Geo::IP->new($flags); +- $self->{geoisp} = Geo::IP->open_type($flag_isp); +- open(STDERR, ">&OLDERR"); +- close(OLDERR); +- } +- }; +- if ($@ || !($self->{geoip} || $self->{geoisp})) { +- $@ =~ s/\s+Trace begun.*//s; +- warn "URILocalBL: GeoIP load failed: $@\n"; +- return 0; +- } +- +- $db_info = sub { return "Geo::IP " . ($self->{geoip}->database_info || '?') }; +- } else { +- dbg("No GeoIP module available"); +- return 0; +- } +- +- my %uri_detail = %{ $permsg->get_uri_detail_list() }; +- my $test = $permsg->{current_rule_name}; +- my $rule = $permsg->{conf}->{uri_local_bl}->{$test}; +- +- my %hit_tests; +- my $got_hit = 0; +- my @addrs; +- my $IP_ADDRESS = IP_ADDRESS; +- +- if ( defined $self->{geoip} ) { +- dbg("check: uri_local_bl evaluating rule %s using database %s\n", $test, $db_info->()); +- } else { +- dbg("check: uri_local_bl evaluating rule %s\n", $test); +- } +- +- my $dns_available = $permsg->is_dns_available(); +- +- while (my ($raw, $info) = each %uri_detail) { +- +- next unless $info->{hosts}; +- +- # look for W3 links only +- next unless (defined $info->{types}->{a} || defined $info->{types}->{parsed}); +- +- while (my($host, $domain) = each %{$info->{hosts}}) { +- +- # skip if the domain name was matched +- if (exists $rule->{exclusions} && exists $rule->{exclusions}->{$domain}) { +- dbg("check: uri_local_bl excludes %s as *.%s\n", $host, $domain); +- next; +- } +- +- if($host !~ /^$IP_ADDRESS$/) { +- if (!$dns_available) { +- dbg("check: uri_local_bl skipping $host, dns not available"); +- next; +- } +- # this would be best cached from prior lookups +- @addrs = gethostbyname($host); +- # convert to string values address list +- @addrs = map { inet_ntoa($_); } @addrs[4..$#addrs]; +- } else { +- @addrs = ($host); +- } +- +- dbg("check: uri_local_bl %s addrs %s\n", $host, join(', ', @addrs)); +- +- for my $ip (@addrs) { +- # skip if the address was matched +- if (exists $rule->{exclusions} && exists $rule->{exclusions}->{$ip}) { +- dbg("check: uri_local_bl excludes %s(%s)\n", $host, $ip); +- next; +- } +- +- if (exists $rule->{countries}) { +- dbg("check: uri_local_bl countries %s\n", join(' ', sort keys %{$rule->{countries}})); +- +- if ( $self->{use_geoip2} == 1 ) { +- my $country; +- if (index($self->{geoip}->metadata()->description()->{en}, 'City') != -1) { +- $country = $self->{geoip}->city( ip => $ip ); +- } else { +- $country = $self->{geoip}->country( ip => $ip ); +- } +- my $country_rec = $country->country(); +- $cc = $country_rec->iso_code(); +- } else { +- $cc = $self->{geoip}->country_code_by_addr($ip); +- } +- +- dbg("check: uri_local_bl host %s(%s) maps to %s\n", $host, $ip, (defined $cc ? $cc : "(undef)")); +- +- # handle there being no associated country (yes, there are holes in +- # the database). +- next unless defined $cc; +- +- # not in blacklist +- next unless (exists $rule->{countries}->{$cc}); +- +- dbg("check: uri_block_cc host %s(%s) matched\n", $host, $ip); +- +- if (would_log('dbg', 'rules') > 1) { +- dbg("check: uri_block_cc criteria for $test met"); +- } +- +- $permsg->test_log("Host: $host in $cc"); +- $hit_tests{$test} = 1; +- +- # reset hash +- keys %uri_detail; +- } +- +- if (exists $rule->{continents}) { +- dbg("check: uri_local_bl continents %s\n", join(' ', sort keys %{$rule->{continents}})); +- +- if ( $self->{use_geoip2} == 1 ) { +- my $country = $self->{geoip}->country( ip => $ip ); +- my $cont_rec = $country->continent(); +- $cont = $cont_rec->{code}; +- } else { +- $cc = $self->{geoip}->country_code_by_addr($ip); +- $cont = $self->{geoip}->continent_code_by_country_code($cc); +- } +- +- dbg("check: uri_local_bl host %s(%s) maps to %s\n", $host, $ip, (defined $cont ? $cont : "(undef)")); +- +- # handle there being no associated continent (yes, there are holes in +- # the database). +- next unless defined $cont; +- +- # not in blacklist +- next unless (exists $rule->{continents}->{$cont}); +- +- dbg("check: uri_block_cont host %s(%s) matched\n", $host, $ip); +- +- if (would_log('dbg', 'rules') > 1) { +- dbg("check: uri_block_cont criteria for $test met"); +- } +- +- $permsg->test_log("Host: $host in $cont"); +- $hit_tests{$test} = 1; +- +- # reset hash +- keys %uri_detail; +- } +- +- if (exists $rule->{isps}) { +- dbg("check: uri_local_bl isps %s\n", join(' ', map { '"' . $_ . '"'; } sort keys %{$rule->{isps}})); +- +- if ( $self->{use_geoip2} == 1 ) { +- $isp = $self->{geoisp}->isp(ip => $ip); +- } else { +- $isp = $self->{geoisp}->isp_by_name($ip); +- } +- +- dbg("check: uri_local_bl isp %s(%s) maps to %s\n", $host, $ip, (defined $isp ? '"' . $isp . '"' : "(undef)")); +- +- # handle there being no associated country +- next unless defined $isp; +- +- # not in blacklist +- next unless (exists $rule->{isps}->{$isp}); +- +- dbg("check: uri_block_isp host %s(%s) matched\n", $host, $ip); +- +- if (would_log('dbg', 'rules') > 1) { +- dbg("check: uri_block_isp criteria for $test met"); +- } +- +- $permsg->test_log("Host: $host in \"$isp\""); +- $hit_tests{$test} = 1; +- +- # reset hash +- keys %uri_detail; +- } +- +- if (exists $rule->{cidr}) { +- dbg("check: uri_block_cidr list %s\n", join(' ', $rule->{cidr}->list_range())); +- +- next unless ($rule->{cidr}->find($ip)); +- +- dbg("check: uri_block_cidr host %s(%s) matched\n", $host, $ip); +- +- if (would_log('dbg', 'rules') > 1) { +- dbg("check: uri_block_cidr criteria for $test met"); +- } +- +- $permsg->test_log("Host: $host as $ip"); +- $hit_tests{$test} = 1; +- +- # reset hash +- keys %uri_detail; +- } +- } +- } +- # cycle through all tests hitted by the uri +- while((my $test_ok) = each %hit_tests) { +- $permsg->got_hit($test_ok); +- $got_hit = 1; +- } +- if($got_hit == 1) { +- return 1; +- } else { +- keys %hit_tests; +- } +- } +- +- dbg("check: uri_local_bl %s no match\n", $test); +- +- return 0; +-} +- +-1; +- +diff --git a/lib/Mail/SpamAssassin/Util/DependencyInfo.pm b/lib/Mail/SpamAssassin/Util/DependencyInfo.pm +index e55c863..b5b05cf 100644 +--- a/lib/Mail/SpamAssassin/Util/DependencyInfo.pm ++++ b/lib/Mail/SpamAssassin/Util/DependencyInfo.pm +@@ -125,46 +125,6 @@ our @OPTIONAL_MODULES = ( + desc => 'Used to check DNS Sender Policy Framework (SPF) records to fight email + address forgery and make it easier to identify spams.', + }, +-{ +- module => 'GeoIP2::Database::Reader', +- version => 0, +- desc => 'Used by the RelayCountry plugin (not enabled by default) to +- determine the domain country codes of each relay in the path of an email. +- Also used by the URILocalBL plugin (not enabled by default) to provide ISP +- and Country code based filtering.', +-}, +-{ +- module => 'Geo::IP', +- version => 0, +- desc => 'Used by the RelayCountry plugin (not enabled by default) to determine +- the domain country codes of each relay in the path of an email. Also used by +- the URILocalBL plugin to provide ISP and Country code based filtering.', +-}, +-{ +- module => 'IP::Country::DB_File', +- version => 0, +- desc => 'Used by the RelayCountry plugin (not enabled by default) to +- determine the domain country codes of each relay in the path of an email. +- Also used by the URILocalBL plugin (not enabled by default) to provide +- Country code based filtering.', +-}, +-{ +- module => 'Net::CIDR::Lite', +- version => 0, +- desc => 'Used by the URILocalBL plugin to process IP address ranges.', +-}, +-{ +- module => 'Razor2::Client::Agent', +- alt_name => 'Razor2', +- version => '2.61', +- desc => 'Used to check message signatures against Vipul\'s Razor collaborative +- filtering network. Razor has a large number of dependencies on CPAN +- modules. Feel free to skip installing it, if this makes you nervous; +- SpamAssassin will still work well without it. +- +- More info on installing and using Razor can be found +- at http://wiki.apache.org/spamassassin/InstallingRazor .', +-}, + #{ + # module => 'Net::Ident', + # version => 0, +diff --git a/rules/init.pre b/rules/init.pre +index f9ee06a..0539b29 100644 +--- a/rules/init.pre ++++ b/rules/init.pre +@@ -14,13 +14,6 @@ + # added to new files, named according to the release they're added in. + ########################################################################### + +-# RelayCountry - add metadata for Bayes learning, marking the countries +-# a message was relayed through +-# +-# Note: This requires the Geo::IP Perl module +-# +-# loadplugin Mail::SpamAssassin::Plugin::RelayCountry +- + # URIDNSBL - look up URLs found in the message against several DNS + # blocklists. + # +diff --git a/rules/v341.pre b/rules/v341.pre +index 489dd4c..7ff8e84 100644 +--- a/rules/v341.pre ++++ b/rules/v341.pre +@@ -19,10 +19,5 @@ + # TxRep - Reputation database that replaces AWL + # loadplugin Mail::SpamAssassin::Plugin::TxRep + +-# URILocalBL - Provides ISP and Country code based filtering as well as +-# quick IP based blocks without a full RBL implementation - Bug 7060 +- +-# loadplugin Mail::SpamAssassin::Plugin::URILocalBL +- + # PDFInfo - Use several methods to detect a PDF file's ham/spam traits + # loadplugin Mail::SpamAssassin::Plugin::PDFInfo +diff --git a/spamassassin.raw b/spamassassin.raw +index 4b52ef9..959297a 100755 +--- a/spamassassin.raw ++++ b/spamassassin.raw +@@ -872,9 +872,6 @@ from the SpamAssassin distribution. + Mail::SpamAssassin::Plugin::Hashcash + perform hashcash verification tests + +- Mail::SpamAssassin::Plugin::RelayCountry +- add message metadata indicating the country code of each relay +- + Mail::SpamAssassin::Plugin::SPF + perform SPF verification tests + diff --git a/SOURCES/spamassassin-cert_update.patch b/SOURCES/spamassassin-cert_update.patch deleted file mode 100644 index 2d0e68f..0000000 --- a/SOURCES/spamassassin-cert_update.patch +++ /dev/null @@ -1,108 +0,0 @@ -commit be7b4d87d84f15446652569cd218db1ced7ae92a -Author: Henrik Krohns -Date: Fri Apr 10 07:47:37 2020 +0000 - - Bug 7807 - t/spamd_ssl.t fails due to small key size - - - git-svn-id: https://svn.apache.org/repos/asf/spamassassin/trunk@1876347 13f79535-47bb-0310-9956-ffa450edef68 - -diff --git a/t/data/etc/testhost.cert b/t/data/etc/testhost.cert -index 86cff9aae..dca7c5a16 100644 ---- a/t/data/etc/testhost.cert -+++ b/t/data/etc/testhost.cert -@@ -1,23 +1,25 @@ - -----BEGIN CERTIFICATE----- --MIIDyjCCAzOgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBpTELMAkGA1UEBhMCU0Ex --CzAJBgNVBAgTAlNBMRowGAYDVQQHExFTcGFtQXNzYXNzaW4gQ2l0eTEVMBMGA1UE --ChMMU3BhbUFzc2Fzc2luMRkwFwYDVQQLExBGT1IgVEVTVElORyBPTkxZMRIwEAYD --VQQDEwlsb2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGHNwYW1hc3Nhc3NpbkBleGFt --cGxlLmNvbTAeFw0wNDA3MDkyMTE4NDdaFw0yNDA3MTQyMTE4NDdaMIGlMQswCQYD --VQQGEwJTQTELMAkGA1UECBMCU0ExGjAYBgNVBAcTEVNwYW1Bc3Nhc3NpbiBDaXR5 --MRUwEwYDVQQKEwxTcGFtQXNzYXNzaW4xGTAXBgNVBAsTEEZPUiBURVNUSU5HIE9O --TFkxEjAQBgNVBAMTCWxvY2FsaG9zdDEnMCUGCSqGSIb3DQEJARYYc3BhbWFzc2Fz --c2luQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1l6To --Fxkyc2glblqZYFq/BWFSMKh9LsouTVowuxC7yQkEENBjeQ4paHUFsi49s0RnabsA --D1c56O8BBT0C89CMiCubRbv/KyHMDut5Nt0brWKS+VRWHgN9T5eYOy3wKPwbc7bm --sPdgt5bOCS78F0luL5T6DPcf5mgE7XAv8qp+mwIDAQABo4IBBjCCAQIwHQYDVR0O --BBYEFGJWfa4QHDeC9Wn3UNLIaf7prjmUMIHSBgNVHSMEgcowgceAFGJWfa4QHDeC --9Wn3UNLIaf7prjmUoYGrpIGoMIGlMQswCQYDVQQGEwJTQTELMAkGA1UECBMCU0Ex --GjAYBgNVBAcTEVNwYW1Bc3Nhc3NpbiBDaXR5MRUwEwYDVQQKEwxTcGFtQXNzYXNz --aW4xGTAXBgNVBAsTEEZPUiBURVNUSU5HIE9OTFkxEjAQBgNVBAMTCWxvY2FsaG9z --dDEnMCUGCSqGSIb3DQEJARYYc3BhbWFzc2Fzc2luQGV4YW1wbGUuY29tggEAMAwG --A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAsKbOfgXZlBm1rQlM6W2Nxf5g --r3QA67liZjVxhIb9chvreCttoe3IkHRSM4axToeKo+x7IV6ceXnqMc5chnu2lUmH --2z7m3IYRYmIOaXroXZcfqX/P4HMw9NOphpEZ4yNsvKSl2n3h3bJ3ErqxMgghlTGD --KYC+xKTFTsPjOE53Jh8= -+MIIELTCCAxWgAwIBAgIUCEYDt5yF4chKPuWTkkbpgLAZWycwDQYJKoZIhvcNAQEL -+BQAwgaUxCzAJBgNVBAYTAlNBMQswCQYDVQQIDAJTQTEaMBgGA1UEBwwRU3BhbUFz -+c2Fzc2luIENpdHkxFTATBgNVBAoMDFNwYW1Bc3Nhc3NpbjEZMBcGA1UECwwQRk9S -+IFRFU1RJTkcgT05MWTESMBAGA1UEAwwJbG9jYWxob3N0MScwJQYJKoZIhvcNAQkB -+FhhzcGFtYXNzYXNzaW5AZXhhbXBsZS5jb20wHhcNMjAwNDEwMDczMTA3WhcNMzAw -+NDA4MDczMTA3WjCBpTELMAkGA1UEBhMCU0ExCzAJBgNVBAgMAlNBMRowGAYDVQQH -+DBFTcGFtQXNzYXNzaW4gQ2l0eTEVMBMGA1UECgwMU3BhbUFzc2Fzc2luMRkwFwYD -+VQQLDBBGT1IgVEVTVElORyBPTkxZMRIwEAYDVQQDDAlsb2NhbGhvc3QxJzAlBgkq -+hkiG9w0BCQEWGHNwYW1hc3Nhc3NpbkBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN -+AQEBBQADggEPADCCAQoCggEBAK+IP5AWcdwiGG33Tt9pAjQ/tWnqhoUoSGHJMq9n -+hV3GI6CyqbbJXN/VFDC27F9qltoZp2eSEigRvLgnrjmnJFJ3H34CcKghx3TfEFdf -+ILCKPXvYSIe7fpeD5+0LN2t+0Kr56vejyGkQAiGDs7FU9rPOHENolU8SvRv102M0 -+K65sZU940ML43ns3JCg1AGGBQj3LabqlxHM+zBAYHFLMd9/fMzKfaFgvyPvZIlIv -+zhzdBksBrl2Wa8RPdJUtWhDGbYMEAHPreZQmiqdtfBbOc946LYYrDTaCAPaAYzUd -+WOqOU9grNcWjIuiIlUjcCPdRe1njDSerfsMdcXUjGroGj90CAwEAAaNTMFEwHQYD -+VR0OBBYEFP8lys2m3PDCcYXieVxpOBaBUX/eMB8GA1UdIwQYMBaAFP8lys2m3PDC -+cYXieVxpOBaBUX/eMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB -+AAuVryADs+3mv4mLLzWPmjBLSzlemqXqZPu7OPe8GrzD3BkovudWErI/nW7OTWcJ -+JixVeL5IgJ/ddDZXIaLM6c73NqcVpOQ+E/vnkbHHJtYTPJ8aSl5DWFd7Pid8JV2M -+gHcNFXStCWQ2XN3iXliDnb7LBI2DphCIBBKGajbP3mlVcVwZstqqyoqRn8wshlrJ -+j7FlrmDF2f62huGBKgfgC4lov95B7TH45hjUnIHaemgVw9VLyZHqw0jQ7Fd14069 -+RMHuzP2DGi6+uJ4rS8pnDGYXHh4Exyl3TXGLAoWFjCmh3TWGRqwbs/VWC6TrbUSe -+mmPZfIFNtvb9bh/uatmTIFU= - -----END CERTIFICATE----- -diff --git a/t/data/etc/testhost.key b/t/data/etc/testhost.key -index 018e89089..e7fc5711a 100644 ---- a/t/data/etc/testhost.key -+++ b/t/data/etc/testhost.key -@@ -1,15 +1,28 @@ -------BEGIN RSA PRIVATE KEY----- --MIICXQIBAAKBgQC1l6ToFxkyc2glblqZYFq/BWFSMKh9LsouTVowuxC7yQkEENBj --eQ4paHUFsi49s0RnabsAD1c56O8BBT0C89CMiCubRbv/KyHMDut5Nt0brWKS+VRW --HgN9T5eYOy3wKPwbc7bmsPdgt5bOCS78F0luL5T6DPcf5mgE7XAv8qp+mwIDAQAB --AoGAXyirQvAvxQ9TCSJuGaezhhxkpnRXJtppGqBwXc75ct5jehzxht79+9cAU87O --ioixlNuEIgDn/bHB5TAAi9aGduwz9hsv4NpNQ89/z7tmRKq43QFpf9hFHxZ3Q4e9 --Hmey7ZsJ3/TpqFNfhH0IkLy6fA5+iClss3b2/6BbqqL8drkCQQDb9TSAJW56LnY2 --aRtImgEyoeg2iEgV98SuDvNNUpTYvG0pkFolFlhb49w5KCmKqOtPA+etc/K2vRJf --8zkfz/BnAkEA01kVZoojg/am0K184Qfotxr7+t8Rjxn4k4g6Eq7ryth/Uicffixx --9E9sp2aadEW+Lt5pao+BsIwxxtLhphkPrQJBALQi1KQ+A4Q8mMNmwNlshp6Yyjwe --0Cpth72ksM0aXJxDdIMdnTXSXvqiWbDVm2/bdxp28D21P4k4vtulrZrICPECQQDP --RzhQ57wrSXWThgLK5KndIy7sfWhIM81yTBHAjyOcPraoSMx/P3HHjTnf+CYVUO1U --JDe5FeO41dZfzCUYdM3FAkA8IXYe74FVG9VM9yzZYbZHaS17TCyztkqagIuUBfDe --g0frip4VCEHvh+qDk678GZ1tMJ30utuTx6JgXJ5HeuFi -------END RSA PRIVATE KEY----- -+-----BEGIN PRIVATE KEY----- -+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCviD+QFnHcIhht -+907faQI0P7Vp6oaFKEhhyTKvZ4VdxiOgsqm2yVzf1RQwtuxfapbaGadnkhIoEby4 -+J645pyRSdx9+AnCoIcd03xBXXyCwij172EiHu36Xg+ftCzdrftCq+er3o8hpEAIh -+g7OxVPazzhxDaJVPEr0b9dNjNCuubGVPeNDC+N57NyQoNQBhgUI9y2m6pcRzPswQ -+GBxSzHff3zMyn2hYL8j72SJSL84c3QZLAa5dlmvET3SVLVoQxm2DBABz63mUJoqn -+bXwWznPeOi2GKw02ggD2gGM1HVjqjlPYKzXFoyLoiJVI3Aj3UXtZ4w0nq37DHXF1 -+Ixq6Bo/dAgMBAAECggEAGrgqtMw12MR344VZxDg/1aQ9ATpp76sKGZh+1qRzcKrQ -+kY2gt+o+8POGd0PhB0U6YUi2atWZXfAVQhMIOk5vAP6RFKVacL1zlx69Zg9c8oKY -+iVmK8N5hjr7Ndw/WB87uBJi2Y6vSvetp56AcoknEo+oj8z7gO4EmuDLbUqaGX65v -+08wyrSoWYAUPDhXvOclReBITDkWuGzhd5IDv3kVmf9oizOO6gbKxh5speFKA91Yg -+WMuBbi7hWB41Nn1ycSKfAx9W7kvBhxA35G/QKupXoTPoNNw5Z08zpg2tiqGlrVFS -+xs5SagfBjxqF2I44y/xH9xv3WuYNPSsQDZANxat+AQKBgQDVbWWryhas9AyyQQdr -+uJRCpBf6Gyzd/FwUnb3370YhK/mVogAIbyT2TwTliXjPYTccvDzP9mWnmH2QVBfG -+e5NW7A3zYwCrculucdKL+PZ58PF/LuCzQUuSlZ72fhqIPHXi3Acipjk6NDLntI/4 -+OF6HO1ZwNqL7tsf2bFjarOjIbQKBgQDSi7+hI6rg/8ovt9UrJYZEv5bR8wHsZRB3 -+4uHvCHHkbNlvZiorAsaVO8w0EoSqT3tsxHTz6l1TskxQhznjru+/mn5QDVu4gHMh -+BFewZ+PRZKxqx61Y1zlvRSHLWM1uXxVcCrBCIC3fFb50oluiCVcI+OE7qXPgX6zN -+Iqd4XB8fMQKBgBT1nVp1iiyJ+wU2ZagqhETXIJOrP4i9U72ikBldIiH305biReaO -+I68cq3pvObID9gmYYtB5fhorW4lk+MDBOgL7Q5N3UYWEz2/NNcQROwNWqiC3VdHE -+w8stbmL+l1Rxu5H/0aORd2VD4wvmK41Q29ej+CUk+HSHyrNkiIVRHbsxAoGBALlq -+rskG8y6QtQsO9uC3fCZBH14nhrMbUcRyfwwVwM8seNQdAde86wtzjOLyx/iAZK6l -+2GUSKTxTEdf9LqLvZV20fbab/QFfxYP3Ig5Nf5jg8uJalLNfXso59Ify3X9spw/W -+reCeHCeRK5flf5MUbJyPKTN0iIK5XyGMejWJ0zKRAoGAc2lrUlT64htPj1//kcgl -+ILzQo51ujjzjOlHYanvN6ekMSfj3Q1ZCTJUp2ArVA64w7Jt16cEEEFCaP4+i9UaW -+aM9/8tho4J29QSllAyxfUIF9i5gcElTfzRhpNGMVrnV/ynyOaTXzUkk7L6FH9soq -+JS3kXA6oQN5NkW6AF/3X314= -+-----END PRIVATE KEY----- diff --git a/SOURCES/spamassassin-check_header.patch b/SOURCES/spamassassin-check_header.patch deleted file mode 100644 index c35396a..0000000 --- a/SOURCES/spamassassin-check_header.patch +++ /dev/null @@ -1,45 +0,0 @@ ---- lib/Mail/SpamAssassin/Conf/Parser.pm (revision 1873634) -+++ lib/Mail/SpamAssassin/Conf/Parser.pm (working copy) -@@ -1244,9 +1244,9 @@ - # no re "strict"; # since perl 5.21.8: Ranges of ASCII printables... - if ($text =~ /^exists:(.*)/) { - my $hdr = $1; -- # never evaled, so can be quite generous with the name - # check :addr etc header options -- if ($hdr !~ /^[^:\s]+:?$/) { -+ # $hdr used in eval text, validate carefully -+ if ($hdr !~ /^[\w.-]+:?$/) { - $self->lint_warn("config: invalid head test $name header: $hdr"); - return; - } -@@ -1254,7 +1254,8 @@ - $conf->{test_opt_header}->{$name} = $hdr; - $conf->{test_opt_exists}->{$name} = 1; - } else { -- if ($text !~ /^([^:\s]+(?:\:|(?:\:[a-z]+){1,2})?)\s*([=!]~)\s*(.+)$/) { -+ # $hdr used in eval text, validate carefully -+ if ($text !~ /^([\w.-]+(?:\:|(?:\:[a-z]+){1,2})?)\s*([=!]~)\s*(.+)$/) { - $self->lint_warn("config: invalid head test $name: $text"); - return; - } ---- lib/Mail/SpamAssassin/Plugin/Check.pm (revision 1873634) -+++ lib/Mail/SpamAssassin/Plugin/Check.pm (working copy) -@@ -716,7 +716,7 @@ - } - - my $def = $conf->{test_opt_unset}->{$rulename}; -- push(@{ $ordered{$hdrname . (!defined $def ? '' : "\t".$def)} }, -+ push(@{ $ordered{$hdrname . (!defined $def ? '' : "\t$rulename")} }, - $rulename); - - return if ($opts{doing_user_rules} && -@@ -740,7 +740,8 @@ - my($hdrname, $def) = split(/\t/, $k, 2); - $self->push_evalstr_prefix($pms, ' - $hval = $self->get(q{'.$hdrname.'}, ' . -- (!defined($def) ? 'undef' : 'q{'.$def.'}') . '); -+ (!defined($def) ? 'undef' : -+ '$self->{conf}->{test_opt_unset}->{q{'.$def.'}}') . '); - '); - foreach my $rulename (@{$v}) { - my $tc_ref = $testcode{$rulename}; diff --git a/SPECS/spamassassin.spec b/SPECS/spamassassin.spec index 86ecc71..ab9b310 100644 --- a/SPECS/spamassassin.spec +++ b/SPECS/spamassassin.spec @@ -53,21 +53,21 @@ %define real_name Mail-SpamAssassin %{!?perl_vendorlib: %define perl_vendorlib %(eval "`%{__perl} -V:installvendorlib`"; echo $installvendorlib)} -%global saversion 3.004004 +%global saversion 3.004006 #%%global prerev rc2 Summary: Spam filter for email which can be invoked from mail delivery agents Name: spamassassin -Version: 3.4.4 +Version: 3.4.6 #Release: 0.8.%%{prerev}%%{?dist} -Release: 4%{?dist} +Release: 1%{?dist} License: ASL 2.0 Group: Applications/Internet URL: https://spamassassin.apache.org/ -Source0: https://www.apache.org/dist/%{name}/source/%{real_name}-%{version}.tar.bz2 #Source0: %%{real_name}-%%{version}-%%{prerev}.tar.bz2 -Source1: https://www.apache.org/dist/%{name}/source/%{real_name}-rules-%{version}.r1873061.tgz +Source0: https://dlcdn.apache.org/dist/%{name}/source/%{real_name}-%{version}.tar.bz2 #Source1: %%{real_name}-rules-%%{version}.%%{prerev}.tgz +Source1: https://dlcdn.apache.org/dist/%{name}/source/%{real_name}-rules-%{version}.r1888502.tgz Source2: redhat_local.cf Source3: spamassassin-default.rc Source4: spamassassin-spamc.rc @@ -92,17 +92,12 @@ Source17: sa-update.timer Patch0: spamassassin-3.3.2-gnupg2.patch Patch1: spamassassin-3.4.1-add-logfile-homedir-options.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1607372 -Patch2: spamassassin-3.4.2-drop-geoip.patch -Patch3: 0001-Drop-the-ResourceLimits-plugin.patch +Patch2: spamassassin-3.4.6-drop-geoip.patch +Patch3: spamassassin-3.4.6-Drop-the-ResourceLimits-plugin.patch %if 0%{?rhel} <= 8 Patch4: spamassassin-sql92_syntax.patch %endif Patch5: spamassassin-disable_tests_for_deleted_modules.patch - -# Patches 100+ are SVN backports (DO NOT REUSE!) - -Patch100: spamassassin-cert_update.patch -Patch101: spamassassin-check_header.patch # end of patches Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) @@ -232,23 +227,16 @@ To filter spam for all users, add that line to /etc/procmailrc %patch0 -p1 %patch1 -p1 %patch2 -p1 -rm -f lib/Mail/SpamAssassin/Plugin/RelayCountry.pm -rm -f lib/Mail/SpamAssassin/Plugin/URILocalBL.pm # Drop the ResourceLimits plugin - it requires perl(BSD::Resource) # which is not in RHEL-8 %patch3 -p1 -rm -f lib/Mail/SpamAssassin/Plugin/ResourceLimits.pm # Reverting this in thel8 to not complicate update process # https://github.com/apache/spamassassin/commit/f7d39bfd3ef2e5ef4a9de480764ee1d73be9349 %if 0%{?rhel} == 8 %patch4 -p1 %endif %patch5 -p1 - -# Patches 100+ are SVN backports (DO NOT REUSE!) -%patch100 -p1 -%patch101 -p0 # end of patches echo "RHEL=%{?rhel} FEDORA=%{?fedora}" @@ -435,6 +423,10 @@ exit 0 %endif %changelog +* Mon Dec 13 2021 Martin Osvald - 3.4.6-1 +- Rebase to v3.4.6 +- Resolves: #1943848 + * Thu Jul 29 2021 Pavel Zhukov - 3.4.4-4.el4 - Fix header parsing