Server IP : 85.214.239.14 / Your IP : 18.219.247.59 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /proc/2/task/2/cwd/usr/share/perl5/Mail/SpamAssassin/Plugin/ |
Upload File : |
# <@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. # </@LICENSE> =head1 NAME Mail::SpamAssassin::Plugin::AccessDB - check message against Access Database =head1 SYNOPSIS loadplugin Mail::SpamAssassin::Plugin::AccessDB header ACCESSDB eval:check_access_database('/etc/mail/access.db') describe ACCESSDB Message would have been caught by accessdb tflags ACCESSDB userconf score ACCESSDB 2 =head1 DESCRIPTION Many MTAs support access databases, such as Sendmail, Postfix, etc. This plugin does similar checks to see whether a message would have been flagged. The rule returns false if an entry isn't found, or the entry has a RHS of I<OK> or I<SKIP>. The rule returns true if an entry exists and has a RHS of I<REJECT>, I<ERROR>, or I<DISCARD>. Note: only the first word (split on non-word characters) of the RHS is checked, so C<error:5.7.1:...> means C<ERROR>. B<AccessDB Pointers:> http://www.faqs.org/docs/securing/chap22sec178.html http://www.postfix.org/access.5.html =cut package Mail::SpamAssassin::Plugin::AccessDB; use Mail::SpamAssassin::Plugin; use Mail::SpamAssassin::Logger; use Fcntl; use strict; use warnings; # use bytes; use re 'taint'; our @ISA = qw(Mail::SpamAssassin::Plugin); use constant HAS_DB_FILE => eval { require DB_File; }; sub new { my $class = shift; my $mailsaobject = shift; $class = ref($class) || $class; my $self = $class->SUPER::new($mailsaobject); bless ($self, $class); $self->register_eval_rule("check_access_database", $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS); return $self; } sub check_access_database { my ($self, $pms, $path) = @_; if (!HAS_DB_FILE) { return 0; } my %access; my %ok = map { $_ => 1 } qw/ OK SKIP /; my %bad = map { $_ => 1 } qw/ REJECT ERROR DISCARD /; $path = $self->{main}->sed_path ($path); dbg("accessdb: tie-ing to DB file R/O in $path"); if (tie %access,"DB_File",$path, O_RDONLY) { my @lookfor; # Look for "From:" versions as well! foreach my $from ($pms->all_from_addrs()) { # $user."\@" # rotate through $domain and check my ($user,$domain) = split(/\@/, $from,2); push(@lookfor, "From:$from",$from); if ($user) { push(@lookfor, "From:$user\@", "$user\@"); } if ($domain) { while ($domain =~ /\./) { push(@lookfor, "From:$domain", $domain); $domain =~ s/^[^.]*\.//; } push(@lookfor, "From:$domain", $domain); } } # we can only match this if we have at least 1 untrusted header if ($pms->{num_relays_untrusted} > 0) { my $lastunt = $pms->{relays_untrusted}->[0]; # If there was a reverse lookup, use it in a lookup if (! $lastunt->{no_reverse_dns}) { my $rdns = $lastunt->{lc_rdns}; while($rdns =~ /\./) { push(@lookfor, "From:$rdns", $rdns); $rdns =~ s/^[^.]*\.//; } push(@lookfor, "From:$rdns", $rdns); } # do both IP and net (rotate over IP) my ($ip) = $lastunt->{ip}; $ip =~ tr/0-9.//cd; while($ip =~ /\./) { push(@lookfor, "From:$ip", $ip); $ip =~ s/\.[^.]*$//; } push(@lookfor, "From:$ip", $ip); } my $retval = 0; my %cache; foreach (@lookfor) { next if ($cache{$_}++); dbg("accessdb: looking for $_"); # Some systems put a null at the end of the key, most don't... my $result = $access{$_} || $access{"$_\000"} || next; my ($type) = split(/\W/,$result); $type = uc $type; if (exists $ok{$type}) { dbg("accessdb: hit OK: $type, $_"); $retval = 0; last; } if (exists $bad{$type} || $type =~ /^\d+$/) { $retval = 1; dbg("accessdb: hit not-OK: $type, $_"); } } dbg("accessdb: untie-ing DB file $path"); untie %access; return $retval; } else { dbg("accessdb: cannot open accessdb $path R/O: $!"); } return 0; } 1;