You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by he...@apache.org on 2018/10/15 17:33:59 UTC
svn commit: r1843928 - in /spamassassin/trunk/lib/Mail: SpamAssassin.pm
SpamAssassin/GeoDB.pm SpamAssassin/Plugin/RelayCountry.pm
SpamAssassin/Plugin/URILocalBL.pm
Author: hege
Date: Mon Oct 15 17:33:59 2018
New Revision: 1843928
URL: http://svn.apache.org/viewvc?rev=1843928&view=rev
Log:
Use single shared GeoDB instance for plugins
Modified:
spamassassin/trunk/lib/Mail/SpamAssassin.pm
spamassassin/trunk/lib/Mail/SpamAssassin/GeoDB.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm
Modified: spamassassin/trunk/lib/Mail/SpamAssassin.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin.pm?rev=1843928&r1=1843927&r2=1843928&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin.pm Mon Oct 15 17:33:59 2018
@@ -1801,6 +1801,21 @@ sub init {
# should be called only after configuration has been parsed
$self->{resolver} = Mail::SpamAssassin::DnsResolver->new($self);
+ # load GeoDB if some plugin wants it
+ if ($self->{geodb_wanted}) {
+ eval '
+ use Mail::SpamAssassin::GeoDB;
+ $self->{geodb} = Mail::SpamAssassin::GeoDB->new({
+ conf => $self->{conf}->{geodb},
+ wanted => $self->{geodb_wanted},
+ });
+ 1;
+ ';
+ if ($@ || !$self->{geodb}) {
+ dbg("config: GeoDB disabled: $@");
+ }
+ }
+
# TODO -- open DNS cache etc. if necessary
}
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/GeoDB.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/GeoDB.pm?rev=1843928&r1=1843927&r2=1843928&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/GeoDB.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/GeoDB.pm Mon Oct 15 17:33:59 2018
@@ -19,6 +19,15 @@
Mail::SpamAssassin::GeoDB - unified interface for geoip modules
+Plugins need to signal SA main package the modules they want loaded
+
+package Mail::SpamAssassin::Plugin::MyPlugin;
+sub new {
+ ...
+ $self->{main}->{geodb_wanted}->{country} = 1;
+ $self->{main}->{geodb_wanted}->{isp} = 1;
+)
+
(internal stuff still subject to change)
=cut
@@ -126,478 +135,511 @@ sub new {
sub init_database {
my ($self, $opts) = @_;
- my $geodb_module = $opts->{conf}->{module} || undef;
- my $geodb_dbs = $opts->{conf}->{options} || {};
- my $geodb_wanted = $opts->{wanted} || {};
-
- my @geoip_search_path = defined $opts->{conf}->{geodb_search_path} ?
- @{$opts->{conf}->{geodb_search_path}} : @geoip_default_path;
+ # Try city too if country wanted
+ $opts->{wanted}->{city} = 1 if $opts->{wanted}->{country};
+ # Try isp too if asn wanted
+ $opts->{wanted}->{isp} = 1 if $opts->{wanted}->{asn};
+
+ my $geodb_opts = {
+ 'module' => $opts->{conf}->{module} || undef,
+ 'dbs' => $opts->{conf}->{options} || undef,
+ 'wanted' => $opts->{wanted} || undef,
+ 'search_path' => defined $opts->{conf}->{geodb_search_path} ?
+ $opts->{conf}->{geodb_search_path} : \@geoip_default_path,
+ };
- my $db;
- my $dbapi;
+ my ($db, $dbapi);
- ##
## GeoIP2
- ##
+ if (!$db && (!$geodb_opts->{module} || $geodb_opts->{module} eq 'geoip2')) {
+ ($db, $dbapi) = $self->load_geoip2($geodb_opts);
+ }
- if (!$db && (!$geodb_module || $geodb_module eq 'geoip2')) {
- my $prep_ok = 0;
- eval {
- require GeoIP2::Database::Reader;
- $prep_ok = 1;
- } or do {
- dbg("geodb: GeoIP2::Database::Reader module load failed: $@");
- };
+ ## Geo::IP
+ if (!$db && (!$geodb_opts->{module} || $geodb_opts->{module} eq 'geoip')) {
+ ($db, $dbapi) = $self->load_geoip($geodb_opts);
+ }
- if ($prep_ok) {
- my %path;
- foreach my $dbtype (@geoip_types) {
- # only autosearch if no absolute path given
- next if %$geodb_dbs && !exists $geodb_dbs->{$dbtype};
- # skip if not needed
- next if %$geodb_wanted && !$geodb_wanted->{$dbtype};
- # skip country if city already loaded
- next if $dbtype eq 'country' && $db->{city};
- # skip asn if isp already loaded
- next if $dbtype eq 'asn' && $db->{isp};
- if (!defined $geodb_dbs->{$dbtype}) {
- # Try some default locations
- PATHS_GEOIP2: foreach my $p (@geoip_search_path) {
- foreach my $f (@{$geoip2_default_files{$dbtype}}) {
- if (-f "$p/$f") {
- $path{$dbtype} = "$p/$f";
- dbg("geodb: GeoIP2: search found $dbtype $p/$f");
- last PATHS_GEOIP2;
- }
- }
- }
- } else {
- if (!-f $geodb_dbs->{$dbtype}) {
- dbg("geodb: GeoIP2: $dbtype database requested, but not found: ".$geodb_dbs->{$dbtype});
- next;
- }
- $path{$dbtype} = $geodb_dbs->{$dbtype};
- }
+ ## IP::Country::DB_File
+ if (!$db && $geodb_opts->{module} && $geodb_opts->{module} eq 'dbfile') {
+ # Only try if geodb_module and path to ipcc.db specified
+ ($db, $dbapi) = $self->load_dbfile($geodb_opts);
+ }
- if (defined $path{$dbtype}) {
- eval {
- $db->{$dbtype} = GeoIP2::Database::Reader->new(
- file => $path{$dbtype},
- locales => [ 'en' ]
- );
- die "unknown error" unless $db->{$dbtype};
- 1;
- } or do {
- $@ =~ s/\s+Trace begun.*//s;
- dbg("geodb: GeoIP2: $dbtype load failed: $@");
- };
- } else {
- my $from = defined $geodb_dbs->{$dbtype} ?
- $geodb_dbs->{$dbtype} : "default locations";
- dbg("geodb: GeoIP2: $dbtype database not found from $from");
- }
+ ## IP::Country::Fast
+ if (!$db && (!$geodb_opts->{module} || $geodb_opts->{module} eq 'fast')) {
+ ($db, $dbapi) = $self->load_fast($geodb_opts);
+ }
- if ($db->{$dbtype}) {
- dbg("geodb: GeoIP2: loaded $dbtype from $path{$dbtype}");
+ if (!$db) {
+ dbg("geodb: No supported database could be loaded");
+ die("No supported GeoDB database could be loaded\n");
+ }
+
+ # country can be aliased to city
+ if (!$dbapi->{country} && $dbapi->{city}) {
+ $dbapi->{country} = $dbapi->{city};
+ }
+ if (!$dbapi->{country_v6} && $dbapi->{city_v6}) {
+ $dbapi->{country_v6} = $dbapi->{city_v6}
+ }
+
+ $self->{db} = $db;
+ $self->{dbapi} = $dbapi;
+
+ foreach (@{$self->get_dbinfo()}) {
+ dbg("geodb: database info: ".$_);
+ }
+ #dbg("geodb: apis available: ".join(', ', sort keys %{$self->{dbapi}}));
+
+ return 1;
+}
+
+sub load_geoip2 {
+ my ($self, $geodb_opts) = @_;
+ my ($db, $dbapi, $ok);
+
+ eval {
+ require GeoIP2::Database::Reader;
+ } or do {
+ dbg("geodb: GeoIP2::Database::Reader module load failed: $@");
+ return (undef, undef);
+ };
+
+ my %path;
+ foreach my $dbtype (@geoip_types) {
+ # only autosearch if no absolute path given
+ next if $geodb_opts->{dbs} && !exists $geodb_opts->{dbs}->{$dbtype};
+ # skip if not needed
+ next if $geodb_opts->{wanted} && !$geodb_opts->{wanted}->{$dbtype};
+ # skip country if city already loaded
+ next if $dbtype eq 'country' && $db->{city};
+ # skip asn if isp already loaded
+ next if $dbtype eq 'asn' && $db->{isp};
+ if (!defined $geodb_opts->{dbs}->{$dbtype}) {
+ # Try some default locations
+ PATHS_GEOIP2: foreach my $p (@{$geodb_opts->{search_path}}) {
+ foreach my $f (@{$geoip2_default_files{$dbtype}}) {
+ if (-f "$p/$f") {
+ $path{$dbtype} = "$p/$f";
+ dbg("geodb: GeoIP2: search found $dbtype $p/$f");
+ last PATHS_GEOIP2;
+ }
}
}
+ } else {
+ if (!-f $geodb_opts->{dbs}->{$dbtype}) {
+ dbg("geodb: GeoIP2: $dbtype database requested, but not found: ".
+ $geodb_opts->{dbs}->{$dbtype});
+ next;
+ }
+ $path{$dbtype} = $geodb_opts->{dbs}->{$dbtype};
}
- # dbinfo_DBTYPE()
- $db->{city} and $dbapi->{dbinfo_city} = sub {
- my $m = $_[0]->{db}->{city}->metadata;
- return "GeoIP2 city: ".$m->description()->{en}." / ".localtime($m->build_epoch());
- };
- $db->{country} and $dbapi->{dbinfo_country} = sub {
- my $m = $_[0]->{db}->{country}->metadata;
- return "GeoIP2 country: ".$m->description()->{en}." / ".localtime($m->build_epoch());
- };
- $db->{isp} and $dbapi->{dbinfo_isp} = sub {
- my $m = $_[0]->{db}->{isp}->metadata;
- return "GeoIP2 isp: ".$m->description()->{en}." / ".localtime($m->build_epoch());
- };
- $db->{asn} and $dbapi->{dbinfo_asn} = sub {
- my $m = $_[0]->{db}->{asn}->metadata;
- return "GeoIP2 asn: ".$m->description()->{en}." / ".localtime($m->build_epoch());
- };
-
- # city()
- $db->{city} and $dbapi->{city} = $dbapi->{city_v6} = sub {
- my $res = {};
- my $city;
- eval {
- $city = $_[0]->{db}->{city}->city(ip=>$_[1]);
- 1;
- } or do {
- $@ =~ s/\s+Trace begun.*//s;
- dbg("geodb: GeoIP2 city query failed for $_[1]: $@");
- return $res;
- };
+ if (defined $path{$dbtype}) {
eval {
- $res->{city_name} = $city->{raw}->{city}->{names}->{en};
- $res->{country} = $city->{raw}->{country}->{iso_code};
- $res->{country_name} = $city->{raw}->{country}->{names}->{en};
- $res->{continent} = $city->{raw}->{continent}->{code};
- $res->{continent_name} = $city->{raw}->{continent}->{names}->{en};
+ $db->{$dbtype} = GeoIP2::Database::Reader->new(
+ file => $path{$dbtype},
+ locales => [ 'en' ]
+ );
+ die "unknown error" unless $db->{$dbtype};
1;
};
- return $res;
- };
-
- # country()
- $db->{country} and $dbapi->{country} = $dbapi->{country_v6} = sub {
- my $res = {};
- my $country;
- eval {
- $country = $_[0]->{db}->{country}->country(ip=>$_[1]);
- 1;
- } or do {
+ if ($@ || !$db->{$dbtype}) {
$@ =~ s/\s+Trace begun.*//s;
- dbg("geodb: GeoIP2 country query failed for $_[1]: $@");
- return $res;
- };
- eval {
- $res->{country} = $country->{raw}->{country}->{iso_code};
- $res->{country_name} = $country->{raw}->{country}->{names}->{en};
- $res->{continent} = $country->{raw}->{continent}->{code};
- $res->{continent_name} = $country->{raw}->{continent}->{names}->{en};
- 1;
- };
+ dbg("geodb: GeoIP2: $dbtype load failed: $@");
+ } else {
+ dbg("geodb: GeoIP2: loaded $dbtype from $path{$dbtype}");
+ $ok = 1;
+ }
+ } else {
+ my $from = defined $geodb_opts->{dbs}->{$dbtype} ?
+ $geodb_opts->{dbs}->{$dbtype} : "default locations";
+ dbg("geodb: GeoIP2: $dbtype database not found from $from");
+ }
+ }
+
+ return (undef, undef) if !$ok;
+
+ # dbinfo_DBTYPE()
+ $db->{city} and $dbapi->{dbinfo_city} = sub {
+ my $m = $_[0]->{db}->{city}->metadata;
+ return "GeoIP2 city: ".$m->description()->{en}." / ".localtime($m->build_epoch());
+ };
+ $db->{country} and $dbapi->{dbinfo_country} = sub {
+ my $m = $_[0]->{db}->{country}->metadata;
+ return "GeoIP2 country: ".$m->description()->{en}." / ".localtime($m->build_epoch());
+ };
+ $db->{isp} and $dbapi->{dbinfo_isp} = sub {
+ my $m = $_[0]->{db}->{isp}->metadata;
+ return "GeoIP2 isp: ".$m->description()->{en}." / ".localtime($m->build_epoch());
+ };
+ $db->{asn} and $dbapi->{dbinfo_asn} = sub {
+ my $m = $_[0]->{db}->{asn}->metadata;
+ return "GeoIP2 asn: ".$m->description()->{en}." / ".localtime($m->build_epoch());
+ };
+
+ # city()
+ $db->{city} and $dbapi->{city} = $dbapi->{city_v6} = sub {
+ my $res = {};
+ my $city;
+ eval {
+ $city = $_[0]->{db}->{city}->city(ip=>$_[1]);
+ 1;
+ } or do {
+ $@ =~ s/\s+Trace begun.*//s;
+ dbg("geodb: GeoIP2 city query failed for $_[1]: $@");
return $res;
};
+ eval {
+ $res->{city_name} = $city->{raw}->{city}->{names}->{en};
+ $res->{country} = $city->{raw}->{country}->{iso_code};
+ $res->{country_name} = $city->{raw}->{country}->{names}->{en};
+ $res->{continent} = $city->{raw}->{continent}->{code};
+ $res->{continent_name} = $city->{raw}->{continent}->{names}->{en};
+ 1;
+ };
+ return $res;
+ };
- # isp()
- $db->{isp} and $dbapi->{isp} = $dbapi->{isp_v6} = sub {
- my $res = {};
- my $isp;
- eval {
- $isp = $_[0]->{db}->{isp}->isp(ip=>$_[1]);
- 1;
- } or do {
- $@ =~ s/\s+Trace begun.*//s;
- dbg("geodb: GeoIP2 isp query failed for $_[1]: $@");
- return $res;
- };
- eval {
- $res->{asn} = $isp->autonomous_system_number();
- $res->{asn_organization} = $isp->autonomous_system_organization();
- $res->{isp} = $isp->isp();
- $res->{organization} = $isp->organization();
- 1;
- };
+ # country()
+ $db->{country} and $dbapi->{country} = $dbapi->{country_v6} = sub {
+ my $res = {};
+ my $country;
+ eval {
+ $country = $_[0]->{db}->{country}->country(ip=>$_[1]);
+ 1;
+ } or do {
+ $@ =~ s/\s+Trace begun.*//s;
+ dbg("geodb: GeoIP2 country query failed for $_[1]: $@");
return $res;
};
+ eval {
+ $res->{country} = $country->{raw}->{country}->{iso_code};
+ $res->{country_name} = $country->{raw}->{country}->{names}->{en};
+ $res->{continent} = $country->{raw}->{continent}->{code};
+ $res->{continent_name} = $country->{raw}->{continent}->{names}->{en};
+ 1;
+ };
+ return $res;
+ };
- # asn()
- $db->{asn} and $dbapi->{asn} = $dbapi->{asn_v6} = sub {
- my $res = {};
- my $asn;
- eval {
- $asn = $_[0]->{db}->{asn}->asn(ip=>$_[1]);
- 1;
- } or do {
- $@ =~ s/\s+Trace begun.*//s;
- dbg("geodb: GeoIP2 asn query failed for $_[1]: $@");
- return $res;
- };
- eval {
- $res->{asn} = $asn->autonomous_system_number();
- $res->{asn_organization} = $asn->autonomous_system_organization();
- 1;
- };
+ # isp()
+ $db->{isp} and $dbapi->{isp} = $dbapi->{isp_v6} = sub {
+ my $res = {};
+ my $isp;
+ eval {
+ $isp = $_[0]->{db}->{isp}->isp(ip=>$_[1]);
+ 1;
+ } or do {
+ $@ =~ s/\s+Trace begun.*//s;
+ dbg("geodb: GeoIP2 isp query failed for $_[1]: $@");
return $res;
};
- }
-
- ##
- ## Geo::IP
- ##
+ eval {
+ $res->{asn} = $isp->autonomous_system_number();
+ $res->{asn_organization} = $isp->autonomous_system_organization();
+ $res->{isp} = $isp->isp();
+ $res->{organization} = $isp->organization();
+ 1;
+ };
+ return $res;
+ };
- if (!$db && (!$geodb_module || $geodb_module eq 'geoip')) {
- my $prep_ok = 0;
- my ($gic_wanted,$gic_have,$gip_wanted,$gip_have);
- my ($flags,$fix_stderr,$can_ipv6);
- eval {
- require Geo::IP;
- # need GeoIP C library 1.6.3 and GeoIP perl API 1.4.4 or later to avoid messages leaking - Bug 7153
- $gip_wanted = version->parse('v1.4.4');
- $gip_have = version->parse(Geo::IP->VERSION);
- $gic_wanted = version->parse('v1.6.3');
- eval { $gic_have = version->parse(Geo::IP->lib_version()); }; # might not have lib_version()
- $gic_have = 'none' if !defined $gic_have;
- dbg("geodb: GeoIP: versions: Geo::IP $gip_have, C library $gic_have");
- $flags = 0;
- $fix_stderr = 0;
- if (ref($gic_have) eq 'version') {
- # this code burps an ugly message if it fails, but that's redirected elsewhere
- eval '$flags = Geo::IP::GEOIP_SILENCE' if $gip_wanted >= $gip_have;
- $fix_stderr = $flags && $gic_wanted >= $gic_have;
- }
- $can_ipv6 = Geo::IP->VERSION >= 1.39 && Geo::IP->api eq 'CAPI';
- $prep_ok = 1;
+ # asn()
+ $db->{asn} and $dbapi->{asn} = $dbapi->{asn_v6} = sub {
+ my $res = {};
+ my $asn;
+ eval {
+ $asn = $_[0]->{db}->{asn}->asn(ip=>$_[1]);
1;
} or do {
- dbg("geodb: Geo::IP module load failed: $@");
+ $@ =~ s/\s+Trace begun.*//s;
+ dbg("geodb: GeoIP2 asn query failed for $_[1]: $@");
+ return $res;
};
+ eval {
+ $res->{asn} = $asn->autonomous_system_number();
+ $res->{asn_organization} = $asn->autonomous_system_organization();
+ 1;
+ };
+ return $res;
+ };
- if ($prep_ok) {
- my %path;
+ return ($db, $dbapi);
+}
- foreach my $dbtype (@geoip_types) {
- # only autosearch if no absolute path given
- next if %$geodb_dbs && !exists $geodb_dbs->{$dbtype};
- # skip if not needed
- next if %$geodb_wanted && !$geodb_wanted->{$dbtype};
- # skip country if city already loaded
- next if $dbtype eq 'country' && $db->{city};
- # skip asn if isp already loaded
- next if $dbtype eq 'asn' && $db->{isp};
- if (!defined $geodb_dbs->{$dbtype}) {
- # Try some default locations
- PATHS_GEOIP: foreach my $p (@geoip_search_path) {
- foreach my $f (@{$geoip_default_files{$dbtype}}) {
+sub load_geoip {
+ my ($self, $geodb_opts) = @_;
+ my ($db, $dbapi, $ok);
+ my ($gic_wanted, $gic_have, $gip_wanted, $gip_have);
+ my ($flags, $fix_stderr, $can_ipv6);
+
+ eval {
+ require Geo::IP;
+ # need GeoIP C library 1.6.3 and GeoIP perl API 1.4.4 or later to avoid messages leaking - Bug 7153
+ $gip_wanted = version->parse('v1.4.4');
+ $gip_have = version->parse(Geo::IP->VERSION);
+ $gic_wanted = version->parse('v1.6.3');
+ eval { $gic_have = version->parse(Geo::IP->lib_version()); }; # might not have lib_version()
+ $gic_have = 'none' if !defined $gic_have;
+ dbg("geodb: GeoIP: versions: Geo::IP $gip_have, C library $gic_have");
+ $flags = 0;
+ $fix_stderr = 0;
+ if (ref($gic_have) eq 'version') {
+ # this code burps an ugly message if it fails, but that's redirected elsewhere
+ eval '$flags = Geo::IP::GEOIP_SILENCE' if $gip_wanted >= $gip_have;
+ $fix_stderr = $flags && $gic_wanted >= $gic_have;
+ }
+ $can_ipv6 = Geo::IP->VERSION >= 1.39 && Geo::IP->api eq 'CAPI';
+ 1;
+ } or do {
+ dbg("geodb: Geo::IP module load failed: $@");
+ return (undef, undef);
+ };
+
+ my %path;
+ foreach my $dbtype (@geoip_types) {
+ # only autosearch if no absolute path given
+ next if $geodb_opts->{dbs} && !exists $geodb_opts->{dbs}->{$dbtype};
+ # skip if not needed
+ next if $geodb_opts->{wanted} && !$geodb_opts->{wanted}->{$dbtype};
+ # skip country if city already loaded
+ next if $dbtype eq 'country' && $db->{city};
+ # skip asn if isp already loaded
+ next if $dbtype eq 'asn' && $db->{isp};
+ if (!defined $geodb_opts->{dbs}->{$dbtype}) {
+ # Try some default locations
+ PATHS_GEOIP: foreach my $p (@{$geodb_opts->{search_path}}) {
+ foreach my $f (@{$geoip_default_files{$dbtype}}) {
+ if (-f "$p/$f") {
+ $path{$dbtype} = "$p/$f";
+ dbg("geodb: GeoIP: search found $dbtype $p/$f");
+ if ($can_ipv6 && $f =~ s/\.(dat)$/v6.$1/i) {
if (-f "$p/$f") {
- $path{$dbtype} = "$p/$f";
+ $path{$dbtype."_v6"} = "$p/$f";
dbg("geodb: GeoIP: search found $dbtype $p/$f");
- if ($can_ipv6 && $f =~ s/\.(dat)$/v6.$1/i) {
- if (-f "$p/$f") {
- $path{$dbtype."_v6"} = "$p/$f";
- dbg("geodb: GeoIP: search found $dbtype $p/$f");
- }
- }
- last PATHS_GEOIP;
}
}
+ last PATHS_GEOIP;
}
- } else {
- if (!-f $geodb_dbs->{$dbtype}) {
- dbg("geodb: GeoIP: $dbtype database requested, but not found: ".$geodb_dbs->{$dbtype});
- next;
- }
- $path{$dbtype} = $geodb_dbs->{$dbtype};
}
}
-
- if (!$can_ipv6) {
- dbg("geodb: GeoIP: IPv6 support not enabled, versions Geo::IP 1.39, GeoIP C API 1.4.7 required");
- }
-
- if ($fix_stderr) {
- open(OLDERR, ">&STDERR");
- open(STDERR, ">/dev/null");
- }
- foreach my $dbtype (@geoip_types) {
- next unless defined $path{$dbtype};
- eval {
- $db->{$dbtype} = Geo::IP->open($path{$dbtype}, Geo::IP->GEOIP_STANDARD | $flags);
- if ($can_ipv6 && defined $path{$dbtype."_v6"}) {
- $db->{$dbtype."_v6"} = Geo::IP->open($path{$dbtype."_v6"}, Geo::IP->GEOIP_STANDARD | $flags);
- }
- };
- if ($@ || !$db->{$dbtype}) {
- dbg("geodb: GeoIP: database $path{$dbtype} load failed: $@");
- };
- }
- if ($fix_stderr) {
- open(STDERR, ">&OLDERR");
- close(OLDERR);
+ } else {
+ if (!-f $geodb_opts->{dbs}->{$dbtype}) {
+ dbg("geodb: GeoIP: $dbtype database requested, but not found: ".
+ $geodb_opts->{dbs}->{$dbtype});
+ next;
}
+ $path{$dbtype} = $geodb_opts->{dbs}->{$dbtype};
}
-
- # dbinfo_DBTYPE()
- $db->{city} and $dbapi->{dbinfo_city} = sub {
- return "Geo::IP IPv4 city: " . ($_[0]->{db}->{city}->database_info || '?')." / IPv6: ".
- ($_[0]->{db}->{city_v6} ? $_[0]->{db}->{city_v6}->database_info || '?' : 'no')
- };
- $db->{country} and $dbapi->{dbinfo_country} = sub {
- return "Geo::IP IPv4 country: " . ($_[0]->{db}->{country}->database_info || '?')." / IPv6: ".
- ($_[0]->{db}->{country_v6} ? $_[0]->{db}->{country_v6}->database_info || '?' : 'no')
- };
- $db->{isp} and $dbapi->{dbinfo_isp} = sub {
- return "Geo::IP IPv4 isp: " . ($_[0]->{db}->{isp}->database_info || '?')." / IPv6: ".
- ($_[0]->{db}->{isp_v6} ? $_[0]->{db}->{isp_v6}->database_info || '?' : 'no')
- };
- $db->{asn} and $dbapi->{dbinfo_asn} = sub {
- return "Geo::IP IPv4 asn: " . ($_[0]->{db}->{asn}->database_info || '?')." / IPv6: ".
- ($_[0]->{db}->{asn_v6} ? $_[0]->{db}->{asn_v6}->database_info || '?' : 'no')
- };
-
- # city()
- $db->{city} and $dbapi->{city} = sub {
- my $res = {};
- my $city;
- if ($_[1] =~ /^$IPV4_ADDRESS$/o) {
- $city = $_[0]->{db}->{city}->record_by_addr($_[1]);
- } elsif ($_[0]->{db}->{city_v6}) {
- $city = $_[0]->{db}->{city_v6}->country_code_by_addr_v6($_[1]);
- return $res if !defined $city;
- $res->{country} = $city;
- return $res;
- }
- if (!defined $city) {
- dbg("geodb: GeoIP city query failed for $_[1]");
- return $res;
- }
- $res->{city_name} = $city->city;
- $res->{country} = $city->country_code;
- $res->{country_name} = $city->country_name;
- $res->{continent} = $city->continent_code;
- return $res;
- };
- $dbapi->{city_v6} = $dbapi->{city} if $db->{city_v6};
-
- # country()
- $db->{country} and $dbapi->{country} = sub {
- my $res = {};
- my $country;
- eval {
- if ($_[1] =~ /^$IPV4_ADDRESS$/o) {
- $country = $_[0]->{db}->{country}->country_code_by_addr($_[1]);
- } elsif ($_[0]->{db}->{country_v6}) {
- $country = $_[0]->{db}->{country_v6}->country_code_by_addr_v6($_[1]);
- }
- 1;
- };
- if (!defined $country) {
- dbg("geodb: GeoIP country query failed for $_[1]");
- return $res;
- };
- $res->{country} = $country;
- $res->{continent} = $country_to_continent{$country} || 'XX';
- return $res;
- };
- $dbapi->{country_v6} = $dbapi->{country} if $db->{country_v6};
-
- # isp()
- $db->{isp} and $dbapi->{isp} = sub {
- my $res = {};
- my $isp;
- eval {
- if ($_[1] =~ /^$IPV4_ADDRESS$/o) {
- $isp = $_[0]->{db}->{isp}->isp_by_addr($_[1]);
- } else {
- # TODO?
- return $res;
- }
- 1;
- };
- if (!defined $isp) {
- dbg("geodb: GeoIP isp query failed for $_[1]");
- return $res;
- };
- $res->{isp} = $isp;
- return $res;
- };
}
- ##
- ## IP::Country::DB_File
- ##
+ if (!$can_ipv6) {
+ dbg("geodb: GeoIP: IPv6 support not enabled, versions Geo::IP 1.39, GeoIP C API 1.4.7 required");
+ }
- # Only try if geodb_module and path to ipcc.db specified
- if (!$db && $geodb_module eq 'dbfile') {
- if (defined $geodb_dbs->{country}) {
- if (-f $geodb_dbs->{country}) {
- eval {
- require IP::Country::DB_File;
- $db->{country} = IP::Country::DB_File->new($geodb_dbs->{country});
- 1;
- };
- if ($@ || !$db->{country}) {
- dbg("geodb: IP::Country::DB_File country load failed: $@");
- } else {
- dbg("geodb: IP::Country::DB_File loaded country from ".$geodb_dbs->{country});
- }
- } else {
- dbg("geodb: IP::Country::DB_File database not found: ".$geodb_dbs->{country});
+ if ($fix_stderr) {
+ open(OLDERR, ">&STDERR");
+ open(STDERR, ">/dev/null");
+ }
+ foreach my $dbtype (@geoip_types) {
+ next unless defined $path{$dbtype};
+ eval {
+ $db->{$dbtype} = Geo::IP->open($path{$dbtype}, Geo::IP->GEOIP_STANDARD | $flags);
+ if ($can_ipv6 && defined $path{$dbtype."_v6"}) {
+ $db->{$dbtype."_v6"} = Geo::IP->open($path{$dbtype."_v6"}, Geo::IP->GEOIP_STANDARD | $flags);
}
+ };
+ if ($@ || !$db->{$dbtype}) {
+ dbg("geodb: GeoIP: database $path{$dbtype} load failed: $@");
} else {
- dbg("geodb: IP::Country::DB_File requires geodb_options country:/path/to/ipcc.db");
+ dbg("geodb: GeoIP: loaded $dbtype from $path{$dbtype}");
+ $ok = 1;
}
+ }
+ if ($fix_stderr) {
+ open(STDERR, ">&OLDERR");
+ close(OLDERR);
+ }
- # dbinfo_DBTYPE()
- $db->{country} and $dbapi->{dbinfo_country} = sub {
- return "IP::Country::DB_File country: ".localtime($_[0]->{db}->{country}->db_time());
- };
+ return (undef, undef) if !$ok;
- # country();
- $db->{country} and $dbapi->{country} = $dbapi->{country_v6} = sub {
- my $res = {};
- my $country;
- if ($_[1] =~ /^$IPV4_ADDRESS$/o) {
- $country = $_[0]->{db}->{country}->inet_atocc($_[1]);
- } else {
- $country = $_[0]->{db}->{country}->inet6_atocc($_[1]);
- }
- if (!defined $country) {
- dbg("geodb: IP::Country::DB_File country query failed for $_[1]");
- return $res;
- };
- $res->{country} = $country;
- $res->{continent} = $country_to_continent{$country} || 'XX';
+ # dbinfo_DBTYPE()
+ $db->{city} and $dbapi->{dbinfo_city} = sub {
+ return "Geo::IP IPv4 city: " . ($_[0]->{db}->{city}->database_info || '?')." / IPv6: ".
+ ($_[0]->{db}->{city_v6} ? $_[0]->{db}->{city_v6}->database_info || '?' : 'no')
+ };
+ $db->{country} and $dbapi->{dbinfo_country} = sub {
+ return "Geo::IP IPv4 country: " . ($_[0]->{db}->{country}->database_info || '?')." / IPv6: ".
+ ($_[0]->{db}->{country_v6} ? $_[0]->{db}->{country_v6}->database_info || '?' : 'no')
+ };
+ $db->{isp} and $dbapi->{dbinfo_isp} = sub {
+ return "Geo::IP IPv4 isp: " . ($_[0]->{db}->{isp}->database_info || '?')." / IPv6: ".
+ ($_[0]->{db}->{isp_v6} ? $_[0]->{db}->{isp_v6}->database_info || '?' : 'no')
+ };
+ $db->{asn} and $dbapi->{dbinfo_asn} = sub {
+ return "Geo::IP IPv4 asn: " . ($_[0]->{db}->{asn}->database_info || '?')." / IPv6: ".
+ ($_[0]->{db}->{asn_v6} ? $_[0]->{db}->{asn_v6}->database_info || '?' : 'no')
+ };
+
+ # city()
+ $db->{city} and $dbapi->{city} = sub {
+ my $res = {};
+ my $city;
+ if ($_[1] =~ /^$IPV4_ADDRESS$/o) {
+ $city = $_[0]->{db}->{city}->record_by_addr($_[1]);
+ } elsif ($_[0]->{db}->{city_v6}) {
+ $city = $_[0]->{db}->{city_v6}->country_code_by_addr_v6($_[1]);
+ return $res if !defined $city;
+ $res->{country} = $city;
return $res;
- };
- }
-
- ##
- ## IP::Country::Fast
- ##
-
- if (!$db && (!$geodb_module || $geodb_module eq 'fast')) {
+ }
+ if (!defined $city) {
+ dbg("geodb: GeoIP city query failed for $_[1]");
+ return $res;
+ }
+ $res->{city_name} = $city->city;
+ $res->{country} = $city->country_code;
+ $res->{country_name} = $city->country_name;
+ $res->{continent} = $city->continent_code;
+ return $res;
+ };
+ $dbapi->{city_v6} = $dbapi->{city} if $db->{city_v6};
+
+ # country()
+ $db->{country} and $dbapi->{country} = sub {
+ my $res = {};
+ my $country;
eval {
- require IP::Country::Fast;
- $db->{country} = IP::Country::Fast->new();
+ if ($_[1] =~ /^$IPV4_ADDRESS$/o) {
+ $country = $_[0]->{db}->{country}->country_code_by_addr($_[1]);
+ } elsif ($_[0]->{db}->{country_v6}) {
+ $country = $_[0]->{db}->{country_v6}->country_code_by_addr_v6($_[1]);
+ }
1;
};
- if ($@ || !$db->{country}) {
- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
- dbg("geodb: IP::Country::Fast load failed: $eval_stat");
- }
-
- # dbinfo_DBTYPE()
- $db->{country} and $dbapi->{dbinfo_country} = sub {
- return "IP::Country::Fast country: ".localtime($_[0]->{db}->{country}->db_time());
+ if (!defined $country) {
+ dbg("geodb: GeoIP country query failed for $_[1]");
+ return $res;
};
-
- # country();
- $db->{country} and $dbapi->{country} = sub {
- my $res = {};
- my $country;
+ $res->{country} = $country;
+ $res->{continent} = $country_to_continent{$country} || 'XX';
+ return $res;
+ };
+ $dbapi->{country_v6} = $dbapi->{country} if $db->{country_v6};
+
+ # isp()
+ $db->{isp} and $dbapi->{isp} = sub {
+ my $res = {};
+ my $isp;
+ eval {
if ($_[1] =~ /^$IPV4_ADDRESS$/o) {
- $country = $_[0]->{db}->{country}->inet_atocc($_[1]);
+ $isp = $_[0]->{db}->{isp}->isp_by_addr($_[1]);
} else {
- return $res
+ # TODO?
+ return $res;
}
- $res->{country} = $country;
- $res->{continent} = $country_to_continent{$country} || 'XX';
+ 1;
+ };
+ if (!defined $isp) {
+ dbg("geodb: GeoIP isp query failed for $_[1]");
return $res;
};
- }
+ $res->{isp} = $isp;
+ return $res;
+ };
- ##
+ return ($db, $dbapi);
+}
- if (!%$db) {
- dbg("geodb: No supported database could be loaded");
- die("No supported GeoDB database could be loaded\n");
+sub load_dbfile {
+ my ($self, $geodb_opts) = @_;
+ my ($db, $dbapi);
+
+ if (!defined $geodb_opts->{dbs}->{country}) {
+ dbg("geodb: IP::Country::DB_File requires geodb_options country:/path/to/ipcc.db");
+ return (undef, undef);
}
- # country can be aliased to city
- if (!$dbapi->{country} && $dbapi->{city}) {
- $dbapi->{country} = $dbapi->{city};
+ if (!-f $geodb_opts->{dbs}->{country}) {
+ dbg("geodb: IP::Country::DB_File database not found: ".$geodb_opts->{dbs}->{country});
+ return (undef, undef);
}
- if (!$dbapi->{country_v6} && $dbapi->{city_v6}) {
- $dbapi->{country_v6} = $dbapi->{city_v6}
+
+ eval {
+ require IP::Country::DB_File;
+ $db->{country} = IP::Country::DB_File->new($geodb_opts->{dbs}->{country});
+ 1;
+ };
+ if ($@ || !$db->{country}) {
+ dbg("geodb: IP::Country::DB_File country load failed: $@");
+ return (undef, undef);
+ } else {
+ dbg("geodb: IP::Country::DB_File loaded country from ".$geodb_opts->{dbs}->{country});
}
- $self->{db} = $db;
- $self->{dbapi} = $dbapi;
+ # dbinfo_DBTYPE()
+ $db->{country} and $dbapi->{dbinfo_country} = sub {
+ return "IP::Country::DB_File country: ".localtime($_[0]->{db}->{country}->db_time());
+ };
+
+ # country();
+ $db->{country} and $dbapi->{country} = $dbapi->{country_v6} = sub {
+ my $res = {};
+ my $country;
+ if ($_[1] =~ /^$IPV4_ADDRESS$/o) {
+ $country = $_[0]->{db}->{country}->inet_atocc($_[1]);
+ } else {
+ $country = $_[0]->{db}->{country}->inet6_atocc($_[1]);
+ }
+ if (!defined $country) {
+ dbg("geodb: IP::Country::DB_File country query failed for $_[1]");
+ return $res;
+ };
+ $res->{country} = $country;
+ $res->{continent} = $country_to_continent{$country} || 'XX';
+ return $res;
+ };
- foreach (@{$self->get_dbinfo()}) {
- dbg("geodb: database info: ".$_);
+ return ($db, $dbapi);
+}
+
+sub load_fast {
+ my ($self, $geodb_opts) = @_;
+ my ($db, $dbapi);
+
+ eval {
+ require IP::Country::Fast;
+ $db->{country} = IP::Country::Fast->new();
+ 1;
+ };
+ if ($@ || !$db->{country}) {
+ my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
+ dbg("geodb: IP::Country::Fast load failed: $eval_stat");
+ return (undef, undef);
}
- #dbg("geodb: apis available: ".join(', ', sort keys %{$self->{dbapi}}));
- return 1;
+ # dbinfo_DBTYPE()
+ $db->{country} and $dbapi->{dbinfo_country} = sub {
+ return "IP::Country::Fast country: ".localtime($_[0]->{db}->{country}->db_time());
+ };
+
+ # country();
+ $db->{country} and $dbapi->{country} = sub {
+ my $res = {};
+ my $country;
+ if ($_[1] =~ /^$IPV4_ADDRESS$/o) {
+ $country = $_[0]->{db}->{country}->inet_atocc($_[1]);
+ } else {
+ return $res
+ }
+ $res->{country} = $country;
+ $res->{continent} = $country_to_continent{$country} || 'XX';
+ return $res;
+ };
+
+ return ($db, $dbapi);
}
# return array, infoline per database type
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm?rev=1843928&r1=1843927&r2=1843928&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/RelayCountry.pm Mon Oct 15 17:33:59 2018
@@ -41,7 +41,6 @@ package Mail::SpamAssassin::Plugin::Rela
use Mail::SpamAssassin::Plugin;
use Mail::SpamAssassin::Logger;
-use Mail::SpamAssassin::GeoDB;
use strict;
use warnings;
# use bytes;
@@ -64,6 +63,9 @@ sub new {
my $self = $class->SUPER::new($mailsaobject);
bless ($self, $class);
+ # we need GeoDB country
+ $self->{main}->{geodb_wanted}->{country} = 1;
+
return $self;
}
@@ -72,27 +74,20 @@ sub extract_metadata {
return if $self->{relaycountry_disabled};
- if (!$self->{geodb}) {
- eval {
- $self->{geodb} = Mail::SpamAssassin::GeoDB->new({
- conf => $opts->{conf}->{geodb},
- wanted => { country => 1, city => 1 },
- });
- };
- if (!$self->{geodb}) {
- dbg("metadata: RelayCountry: plugin disabled: $@");
- $self->{relaycountry_disabled} = 1;
- return;
- }
+ if (!$self->{main}->{geodb} ||
+ !$self->{main}->{geodb}->can('country')) {
+ dbg("metadata: RelayCountry: plugin disabled, GeoDB country not available");
+ $self->{relaycountry_disabled} = 1;
+ return;
}
- my $geodb = $self->{geodb};
my $msg = $opts->{msg};
+ my $geodb = $self->{main}->{geodb};
my $countries = '';
foreach my $relay (@{$msg->{metadata}->{relays_untrusted}}) {
my $ip = $relay->{ip};
- my $cc = $self->{geodb}->get_country($ip);
+ my $cc = $geodb->get_country($ip);
$countries .= $cc." ";
}
@@ -104,7 +99,7 @@ sub extract_metadata {
sub parsed_metadata {
my ($self, $opts) = @_;
- return 1 unless $self->{geodb};
+ return 1 if $self->{relaycountry_disabled};
my $countries =
$opts->{permsgstatus}->get_message->get_metadata('X-Relay-Countries');
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm?rev=1843928&r1=1843927&r2=1843928&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm Mon Oct 15 17:33:59 2018
@@ -108,7 +108,6 @@ package Mail::SpamAssassin::Plugin::URIL
use Mail::SpamAssassin::Plugin;
use Mail::SpamAssassin::Constants qw(:ip);
use Mail::SpamAssassin::Util qw(untaint_var idn_to_ascii);
-use Mail::SpamAssassin::GeoDB;
use Mail::SpamAssassin::NetSet;
use Socket;
@@ -142,6 +141,10 @@ sub new {
$self->register_eval_rule("check_uri_local_bl");
$self->set_config($mailsaobject->{conf});
+ # we need GeoDB country/isp
+ $self->{main}->{geodb_wanted}->{country} = 1;
+ $self->{main}->{geodb_wanted}->{isp} = 1;
+
return $self;
}
@@ -339,29 +342,18 @@ sub finish_parsing_end {
}
}
-sub _init_geodb {
- my ($self, $pms) = @_;
- if (!$self->{geodb}) {
- eval {
- $self->{geodb} = Mail::SpamAssassin::GeoDB->new({
- conf => $pms->{conf}->{geodb},
- wanted => { country => 1, city => 1, isp => 1 },
- });
- };
- if (!$self->{geodb}) {
- dbg("plugin disabled: $@");
- $self->{urilocalbl_disabled} = 1;
- return 0;
- }
- }
- return 1;
-}
-
sub check_uri_local_bl {
my ($self, $pms) = @_;
return 0 if $self->{urilocalbl_disabled};
- return 0 if !$self->_init_geodb($pms);
+
+ if (!$self->{main}->{geodb} ||
+ (!$self->{main}->{geodb}->can('country') &&
+ !$self->{main}->{geodb}->can('isp'))) {
+ dbg("plugin disabled, GeoDB country/isp not available");
+ $self->{urilocalbl_disabled} = 1;
+ return 0;
+ }
my $rulename = $pms->get_current_eval_rule_name();
my $ruleconf = $pms->{conf}->{urilocalbl}->{$rulename};
@@ -414,7 +406,7 @@ sub check_uri_local_bl {
sub { my($ent, $pkt) = @_;
$self->_finish_lookup($pms, $ent, $pkt); },
master_deadline => $pms->{master_deadline}
- ) if $self->{geodb}->can('country_v6');
+ ) if $self->{main}->{geodb}->can('country_v6');
}
}
@@ -453,6 +445,7 @@ sub _check_host {
my ($self, $pms, $rulename, $host, $addrs) = @_;
my $ruleconf = $pms->{conf}->{urilocalbl}->{$rulename};
+ my $geodb = $self->{main}->{geodb};
if ($host ne $addrs->[0]) {
dbg("resolved $host: ".join(', ', @$addrs));
@@ -474,7 +467,7 @@ sub _check_host {
dbg("checking $host for countries: $testcc");
}
foreach my $ip (@$addrs) {
- my $cc = $self->{geodb}->get_country($ip);
+ my $cc = $geodb->get_country($ip);
if ( (!$neg && defined $ruleconf->{countries}{$cc}) ||
($neg && !defined $ruleconf->{countries}{$cc}) ) {
dbg("$host ($ip) country $cc - HIT");
@@ -496,7 +489,7 @@ sub _check_host {
dbg("checking $host for continents: $testcont");
}
foreach my $ip (@$addrs) {
- my $cc = $self->{geodb}->get_continent($ip);
+ my $cc = $geodb->get_continent($ip);
if ( (!$neg && defined $ruleconf->{continents}{$cc}) ||
($neg && !defined $ruleconf->{continents}{$cc}) ) {
dbg("$host ($ip) continent $cc - HIT");
@@ -510,12 +503,12 @@ sub _check_host {
}
if (defined $ruleconf->{isps}) {
- if ($self->{geodb}->can('isp')) {
+ if ($geodb->can('isp')) {
my $testisp = join(', ', map {"\"$_\""} sort values %{$ruleconf->{isps}});
dbg("checking $host for isps: $testisp");
foreach my $ip (@$addrs) {
- my $isp = $self->{geodb}->get_isp($ip);
+ my $isp = $geodb->get_isp($ip);
next unless defined $isp;
my $ispkey = uc($isp); $ispkey =~ s/\s+//gs;
if (defined $ruleconf->{isps}{$ispkey}) {