You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by do...@apache.org on 2005/03/11 04:37:04 UTC
svn commit: r157037 - in spamassassin/trunk:
lib/Mail/SpamAssassin/EvalTests.pm lib/Mail/SpamAssassin/Plugin/SPF.pm
rules/50_scores.cf rules/60_whitelist.cf
Author: dos
Date: Thu Mar 10 19:37:02 2005
New Revision: 157037
URL: http://svn.apache.org/viewcvs?view=rev&rev=157037
Log:
bug 3487: implements whitelist_from_spf & def_whitelist_from_spf
Modified:
spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/SPF.pm
spamassassin/trunk/rules/50_scores.cf
spamassassin/trunk/rules/60_whitelist.cf
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm?view=diff&r1=157036&r2=157037
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm Thu Mar 10 19:37:02 2005
@@ -100,6 +100,12 @@
}
}
+sub check_for_matching_env_and_hdr_from {
+ my ($self) =@_;
+ # two blank headers match so don't bother checking
+ return (lc $self->get('EnvelopeFrom:addr') eq lc $self->get('From:addr'));
+}
+
sub sorted_recipients {
my ($self) = @_;
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/SPF.pm
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/SPF.pm?view=diff&r1=157036&r2=157037
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/SPF.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/SPF.pm Thu Mar 10 19:37:02 2005
@@ -61,12 +61,62 @@
$self->register_eval_rule ("check_for_spf_helo_pass");
$self->register_eval_rule ("check_for_spf_helo_fail");
$self->register_eval_rule ("check_for_spf_helo_softfail");
+ $self->register_eval_rule ("check_for_spf_whitelist_from");
+ $self->register_eval_rule ("check_for_def_spf_whitelist_from");
+
+ $self->set_config($mailsaobject->{conf});
return $self;
}
###########################################################################
+sub set_config {
+ my($self, $conf) = @_;
+ my @cmds = ();
+
+=item whitelist_from_spf add@ress.com
+
+Use this to supplement the whitelist_from addresses with a check against the
+domain's SPF record. Aside from the name 'whitelist_from_spf', the syntax is
+exactly the same as the syntax for 'whitelist_from'.
+
+Just like whitelist_from, multiple addresses per line, separated by spaces,
+are OK. Multiple C<whitelist_from_spf> lines are also OK.
+
+The headers checked for whitelist_from_spf addresses are the same headers
+used for SPF checks (Envelope-From, Return-Path, X-Envelope-From, etc).
+
+Since this whitelist requires an SPF check to be made network tests must be
+enabled. It is also required that your trust path be correctly configured.
+See the section on C<trusted_networks> for more info on trust paths.
+
+e.g.
+
+ whitelist_from_spf joe@example.com fred@example.com
+ whitelist_from_spf *@example.com
+
+=item def_whitelist_from_spf add@ress.com
+
+Same as C<whitelist_from_spf>, but used for the default whitelist entries
+in the SpamAssassin distribution. The whitelist score is lower, because
+these are often targets for spammer spoofing.
+
+=cut
+
+ push (@cmds, {
+ setting => 'whitelist_from_spf',
+ type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST
+ });
+
+ push (@cmds, {
+ setting => 'def_whitelist_from_spf',
+ type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST
+ });
+
+ $conf->{parser}->register_commands(\@cmds);
+}
+
# SPF support
sub check_for_spf_pass {
my ($self, $scanner) = @_;
@@ -116,6 +166,18 @@
$scanner->{spf_helo_softfail};
}
+sub check_for_spf_whitelist_from {
+ my ($self, $scanner) = @_;
+ $self->_check_spf_whitelist($scanner) unless $scanner->{spf_whitelist_from_checked};
+ $scanner->{spf_whitelist_from};
+}
+
+sub check_for_def_spf_whitelist_from {
+ my ($self, $scanner) = @_;
+ $self->_check_def_spf_whitelist($scanner) unless $scanner->{def_spf_whitelist_from_checked};
+ $scanner->{def_spf_whitelist_from};
+}
+
sub _check_spf {
my ($self, $scanner, $ishelo) = @_;
@@ -150,7 +212,7 @@
my $ip = $lasthop->{ip};
my $helo = $lasthop->{helo};
- my $sender = '';
+ $scanner->{sender} = '' unless $scanner->{sender_got};
if ($ishelo) {
dbg("spf: checking HELO (helo=$helo, ip=$ip)");
@@ -163,34 +225,13 @@
dbg("spf: trimmed HELO down to '$helo'");
} else {
- $sender = $lasthop->{envfrom};
-
- if ($sender) {
- dbg("spf: found Envelope-From in last untrusted Received header");
- }
- else {
- # We cannot use the env-from data, since it went through 1 or
- # more relays since the untrusted sender and they may have
- # rewritten it.
- #
- if ($scanner->{num_relays_trusted} > 0) {
- dbg("spf: relayed through one or more trusted relays, cannot use header-based Envelope-From, skipping");
- return;
- }
-
- # we can (apparently) use whatever the current Envelope-From was,
- # from the Return-Path, X-Envelope-From, or whatever header.
- # it's better to get it from Received though, as that is updated
- # hop-by-hop.
- #
- $sender = $scanner->get ("EnvelopeFrom");
- }
+ $self->_get_sender($scanner) unless $scanner->{sender_got};
- if (!$sender) {
- dbg("spf: cannot get Envelope-From, cannot use SPF");
+ if (!$scanner->{sender}) {
+ # we already dbg'd that we couldn't get an Envelope-From and can't do SPF
return;
}
- dbg("spf: checking EnvelopeFrom (helo=$helo, ip=$ip, envfrom=$sender)");
+ dbg("spf: checking EnvelopeFrom (helo=$helo, ip=$ip, envfrom=$scanner->{sender})");
}
# this test could probably stand to be more strict, but try to test
@@ -216,7 +257,7 @@
die "spf: Mail::SPF::Query 1.996 or later required, this is $Mail::SPF::Query::VERSION\n";
}
$query = Mail::SPF::Query->new (ip => $ip,
- sender => $sender,
+ sender => $scanner->{sender},
helo => $helo,
debug => Mail::SpamAssassin::dbg_check('+rbl'),
trusted => 0);
@@ -272,7 +313,124 @@
}
}
- dbg("spf: query for $sender/$ip/$helo: result: $result, comment: $comment");
+ dbg("spf: query for $scanner->{sender}/$ip/$helo: result: $result, comment: $comment");
+}
+
+sub _get_sender {
+ my ($self, $scanner) = @_;
+ my $sender;
+
+ $scanner->{sender_got} = 1;
+ $scanner->{sender} = '';
+
+ if (exists($scanner->{relays_untrusted}->[0])) {
+ $sender = $scanner->{relays_untrusted}->[0]->{envfrom};
+ }
+
+ if ($sender) {
+ dbg("spf: found Envelope-From in last untrusted Received header");
+ }
+ else {
+ # We cannot use the env-from data, since it went through 1 or more relays
+ # since the untrusted sender and they may have rewritten it.
+ if ($scanner->{num_relays_trusted} > 0) {
+ dbg("spf: relayed through one or more trusted relays, cannot use header-based Envelope-From, skipping");
+ return;
+ }
+
+ # we can (apparently) use whatever the current Envelope-From was,
+ # from the Return-Path, X-Envelope-From, or whatever header.
+ # it's better to get it from Received though, as that is updated
+ # hop-by-hop.
+ $sender = $scanner->get ("EnvelopeFrom");
+ }
+
+ if (!$sender) {
+ dbg("spf: cannot get Envelope-From, cannot use SPF");
+ return; # avoid setting $scanner->{sender} to undef
+ }
+
+ return $scanner->{sender} = lc $sender;
+}
+
+sub _check_spf_whitelist {
+ my ($self, $scanner) = @_;
+
+ return unless $scanner->is_dns_available();
+
+ $scanner->{spf_whitelist_from_checked} = 1;
+ $scanner->{spf_whitelist_from} = 0;
+
+ $self->_get_sender($scanner) unless $scanner->{sender_got};
+
+ unless ($scanner->{sender}) {
+ dbg("spf: spf_whitelist_from: could not find useable envelope sender");
+ return;
+ }
+
+ if (defined ($scanner->{conf}->{whitelist_from_spf}->{$scanner->{sender}})) {
+ $scanner->{spf_whitelist_from} = 1;
+ } else {
+ study $scanner->{sender};
+ foreach my $regexp (values %{$scanner->{conf}->{whitelist_from_spf}}) {
+ if ($scanner->{sender} =~ qr/$regexp/i) {
+ $scanner->{spf_whitelist_from} = 1;
+ last;
+ }
+ }
+ }
+
+ # if the message doesn't pass SPF validation, it can't pass an SPF whitelist
+ if ($scanner->{spf_whitelist_from}) {
+ if ($self->check_for_spf_pass($scanner)) {
+ dbg("spf: whitelist_from_spf: $scanner->{sender} is in user's WHITELIST_FROM_SPF and passed SPF check");
+ } else {
+ dbg("spf: whitelist_from_spf: $scanner->{sender} is in user's WHITELIST_FROM_SPF but failed SPF check");
+ $scanner->{spf_whitelist_from} = 0;
+ }
+ } else {
+ dbg("spf: whitelist_from_spf: $scanner->{sender} is not in user's WHITELIST_FROM_SPF");
+ }
+}
+
+sub _check_def_spf_whitelist {
+ my ($self, $scanner) = @_;
+
+ return unless $scanner->is_dns_available();
+
+ $scanner->{def_spf_whitelist_from_checked} = 1;
+ $scanner->{def_spf_whitelist_from} = 0;
+
+ $self->_get_sender($scanner) unless $scanner->{sender_got};
+
+ unless ($scanner->{sender}) {
+ dbg("spf: def_spf_whitelist_from: could not find useable envelope sender");
+ return;
+ }
+
+ if (defined ($scanner->{conf}->{def_whitelist_from_spf}->{$scanner->{sender}})) {
+ $scanner->{def_spf_whitelist_from} = 1;
+ } else {
+ study $scanner->{sender};
+ foreach my $regexp (values %{$scanner->{conf}->{def_whitelist_from_spf}}) {
+ if ($scanner->{sender} =~ qr/$regexp/i) {
+ $scanner->{def_spf_whitelist_from} = 1;
+ last;
+ }
+ }
+ }
+
+ # if the message doesn't pass SPF validation, it can't pass an SPF whitelist
+ if ($scanner->{def_spf_whitelist_from}) {
+ if ($self->check_for_spf_pass($scanner)) {
+ dbg("spf: def_whitelist_from_spf: $scanner->{sender} is in DEF_WHITELIST_FROM_SPF and passed SPF check");
+ } else {
+ dbg("spf: def_whitelist_from_spf: $scanner->{sender} is in DEF_WHITELIST_FROM_SPF but failed SPF check");
+ $scanner->{def_spf_whitelist_from} = 0;
+ }
+ } else {
+ dbg("spf: def_whitelist_from_spf: $scanner->{sender} is not in DEF_WHITELIST_FROM_SPF");
+ }
}
###########################################################################
Modified: spamassassin/trunk/rules/50_scores.cf
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/rules/50_scores.cf?view=diff&r1=157036&r2=157037
==============================================================================
--- spamassassin/trunk/rules/50_scores.cf (original)
+++ spamassassin/trunk/rules/50_scores.cf Thu Mar 10 19:37:02 2005
@@ -587,6 +587,12 @@
score USER_IN_DEF_WHITELIST -15.000
score USER_IN_BLACKLIST_TO 10.000
+ifplugin Mail::SpamAssassin::Plugin::SPF
+score USER_IN_SPF_WHITELIST -100.000
+score USER_IN_DEF_SPF_WL -7.500
+score ENV_AND_HDR_SPF_MATCH -7.500
+endif # Mail::SpamAssassin::Plugin::SPF
+
# not really false positives but the user wants spam!
score USER_IN_WHITELIST_TO -6.000
score USER_IN_MORE_SPAM_TO -20.000
Modified: spamassassin/trunk/rules/60_whitelist.cf
URL: http://svn.apache.org/viewcvs/spamassassin/trunk/rules/60_whitelist.cf?view=diff&r1=157036&r2=157037
==============================================================================
--- spamassassin/trunk/rules/60_whitelist.cf (original)
+++ spamassassin/trunk/rules/60_whitelist.cf Thu Mar 10 19:37:02 2005
@@ -42,6 +42,19 @@
describe USER_IN_DEF_WHITELIST From: address is in the default white-list
tflags USER_IN_DEF_WHITELIST userconf nice noautolearn
+header USER_IN_SPF_WHITELIST eval:check_for_spf_whitelist_from()
+describe USER_IN_SPF_WHITELIST From: address is in the user's SPF whitelist
+tflags USER_IN_SPF_WHITELIST userconf nice noautolearn net
+
+header USER_IN_DEF_SPF_WL eval:check_for_def_spf_whitelist_from()
+describe USER_IN_DEF_SPF_WL From: address is in the default SPF white-list
+tflags USER_IN_DEF_SPF_WL userconf nice noautolearn net
+
+header __ENV_AND_HDR_FROM_MATCH eval:check_for_matching_env_and_hdr_from()
+meta ENV_AND_HDR_SPF_MATCH (USER_IN_DEF_SPF_WL && __ENV_AND_HDR_FROM_MATCH)
+describe ENV_AND_HDR_SPF_MATCH Env and Hdr From used in default SPF WL Match
+tflags ENV_AND_HDR_SPF_MATCH userconf nice noautolearn net
+
header USER_IN_BLACKLIST_TO eval:check_to_in_blacklist()
describe USER_IN_BLACKLIST_TO User is listed in 'blacklist_to'
tflags USER_IN_BLACKLIST_TO userconf nice noautolearn
@@ -70,68 +83,81 @@
# Please do not add unmoderated public mailing lists here. They are
# too easily abused by spammers.
+# we need the SPF plugin to do SPF validated whitelists, so:
+ifplugin Mail::SpamAssassin::Plugin::SPF
+
+def_whitelist_from_spf *@nytimes.com
+def_whitelist_from_spf *@amazon.com
+def_whitelist_from_spf *@*.amazon.com
+def_whitelist_from_spf *@amazon.co.uk
+def_whitelist_from_spf *@*.amazon.co.uk
+def_whitelist_from_spf *@ora.com
+def_whitelist_from_spf *@*.ora.com
+def_whitelist_from_spf *@bn.com
+def_whitelist_from_spf *@mypoints.com
+def_whitelist_from_spf *@*.mypoints.com
+def_whitelist_from_spf *@paypal.com
+def_whitelist_from_spf *@ebay.com
+def_whitelist_from_spf *@foolsubs.com
+def_whitelist_from_spf *@match.com
+
+# bugtraq: can contain malicious Javascript etc.
+def_whitelist_from_spf *@securityfocus.com
+
+def_whitelist_from_spf *@mediaunspun.imakenews.net
+
+# sender of Cringley newsletter
+def_whitelist_from_spf *@bdcimail.com
+
+# Silicon.com newslettters - we see thousands of these
+def_whitelist_from_spf *@silicon.com
+
+# C|Net news.com newsletters
+def_whitelist_from_spf *@newsletter.online.com
+
+# bug 1348
+def_whitelist_from_spf *@enews.buy.com
+def_whitelist_from_spf *@palm.m0.net
+def_whitelist_from_spf *@handspring.4at1.com
+
+endif # Mail::SpamAssassin::Plugin::SPF
+
+
+# the remaining default whitelists use the received headers and do not require
+# the SPF plugin
+
def_whitelist_from_rcvd billing@networksolutions.com networksolutions.com
def_whitelist_from_rcvd outbound-response@networksolutions.com networksolutions.com
def_whitelist_from_rcvd hostmaster@internic.net internic.net
def_whitelist_from_rcvd support@register.com register.com
-def_whitelist_from_rcvd nytdirect@nytimes.com nytimes.com
-def_whitelist_from_rcvd petitions@petitiononline.com petitiononline.com
-def_whitelist_from_rcvd *@amazon.com amazon.com
-def_whitelist_from_rcvd *@*.amazon.com amazon.com
-def_whitelist_from_rcvd *@amazon.co.uk amazon.com
-def_whitelist_from_rcvd *@*.amazon.co.uk amazon.com
-def_whitelist_from_rcvd *@ora.com oreilly.com
-def_whitelist_from_rcvd *@*.ora.com oreilly.com
+def_whitelist_from_rcvd petitions@petitiononline.com petitiononline.com
def_whitelist_from_rcvd *@walmart.com walmart.com
-def_whitelist_from_rcvd *@bn.com bn.com
def_whitelist_from_rcvd *@online.telstra.com.au telstra.com.au
-
def_whitelist_from_rcvd *@yahoo-inc.com yahoo-inc.com
def_whitelist_from_rcvd *@yahoo-inc.com yahoo.com
-def_whitelist_from_rcvd *@mypoints.com mypoints.com
-def_whitelist_from_rcvd *@*.mypoints.com mypoints.com
def_whitelist_from_rcvd *@orbitz.com orbitz.com
-def_whitelist_from_rcvd *@paypal.com paypal.com
-
-# bugtraq: can contain malicious Javascript etc.
-def_whitelist_from_rcvd *@securityfocus.com securityfocus.com
-def_whitelist_from_rcvd *@LISTSERV.NTBUGTRAQ.COM lsoft.com
+def_whitelist_from_rcvd *@LISTSERV.NTBUGTRAQ.COM lsoft.com
def_whitelist_from_rcvd freshmeat-news-admin@lists.freshmeat.net freshmeat.net
def_whitelist_from_rcvd *@mailer.whitehat.com whitehat.com
-def_whitelist_from_rcvd *@mediaunspun.imakenews.net imakenews.com
def_whitelist_from_rcvd *@spamex.com spamex.com
+def_whitelist_from_rcvd *enotify@usenix.org voyager.usenix.org
-def_whitelist_from_rcvd *enotify@usenix.org voyager.usenix.org
-
-# sender of Cringley newsletter
-def_whitelist_from_rcvd *@bdcimail.com mailcontrol.bellevuedata.com
# internet.com lists
-def_whitelist_from_rcvd listsupport@internet.com lyris.net
-
-# Silicon.com newslettters - we see thousands of these
-def_whitelist_from_rcvd *@silicon.com lists.nmtv.net
+def_whitelist_from_rcvd listsupport@internet.com lyris.net
# FT.com newsletters
-def_whitelist_from_rcvd *@newsbyemail.ft.com lodo.exactis.com
-
-# C|Net news.com newsletters
-def_whitelist_from_rcvd *@newsletter.online.com cnet.com
+def_whitelist_from_rcvd *@newsbyemail.ft.com lodo.exactis.com
# Friends re-united (popular UK old-school-network)
-def_whitelist_from_rcvd *@friendsreunited.co.uk friendsreunited.co.uk
+def_whitelist_from_rcvd *@friendsreunited.co.uk friendsreunited.co.uk
# RFC Editor mails
-def_whitelist_from_rcvd rfc-editor@rfc-editor.org isi.edu
-
-# Verisign: bug 1056
-def_whitelist_from_rcvd *@*.nsi-direct.com e-dialog.com
+def_whitelist_from_rcvd rfc-editor@rfc-editor.org isi.edu
+def_whitelist_from_rcvd *@*.nsi-direct.com e-dialog.com
# bug 1348
-def_whitelist_from_rcvd *@warehouse.com warehouse.com
-def_whitelist_from_rcvd *@enews.buy.com enews.buy.com
-def_whitelist_from_rcvd *@palm.m0.net palm.m0.net
-def_whitelist_from_rcvd *@handspring.4at1.com handspring.4at1.com
-def_whitelist_from_rcvd *@*.efax.com efax.com
+def_whitelist_from_rcvd *@warehouse.com warehouse.com
+def_whitelist_from_rcvd *@*.efax.com efax.com