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/11/08 10:53:47 UTC
svn commit: r1846123 - in /spamassassin/trunk: MANIFEST UPGRADE
lib/Mail/SpamAssassin/Plugin/AuthRes.pm t/all_modules.t t/authres.t
t/data/nice/authres
Author: hege
Date: Thu Nov 8 10:53:46 2018
New Revision: 1846123
URL: http://svn.apache.org/viewvc?rev=1846123&view=rev
Log:
New AuthRes plugin - Bug 6918
Added:
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AuthRes.pm
spamassassin/trunk/t/authres.t (with props)
spamassassin/trunk/t/data/nice/authres
Modified:
spamassassin/trunk/MANIFEST
spamassassin/trunk/UPGRADE
spamassassin/trunk/t/all_modules.t
Modified: spamassassin/trunk/MANIFEST
URL: http://svn.apache.org/viewvc/spamassassin/trunk/MANIFEST?rev=1846123&r1=1846122&r2=1846123&view=diff
==============================================================================
--- spamassassin/trunk/MANIFEST (original)
+++ spamassassin/trunk/MANIFEST Thu Nov 8 10:53:46 2018
@@ -75,6 +75,7 @@ lib/Mail/SpamAssassin/Plugin/ASN.pm
lib/Mail/SpamAssassin/Plugin/AWL.pm
lib/Mail/SpamAssassin/Plugin/AccessDB.pm
lib/Mail/SpamAssassin/Plugin/AntiVirus.pm
+lib/Mail/SpamAssassin/Plugin/AuthRes.pm
lib/Mail/SpamAssassin/Plugin/AutoLearnThreshold.pm
lib/Mail/SpamAssassin/Plugin/Bayes.pm
lib/Mail/SpamAssassin/Plugin/BodyEval.pm
@@ -230,6 +231,7 @@ t/README
t/SATest.pl
t/SATest.pm
t/all_modules.t
+t/authres.t
t/autolearn.t
t/autolearn_force.t
t/autolearn_force_fail.t
@@ -325,6 +327,7 @@ t/data/nice/013
t/data/nice/014
t/data/nice/015
t/data/nice/016
+t/data/nice/authres
t/data/nice/base64.txt
t/data/nice/crlf-endings
t/data/nice/dkim/AddedVtag_07
Modified: spamassassin/trunk/UPGRADE
URL: http://svn.apache.org/viewvc/spamassassin/trunk/UPGRADE?rev=1846123&r1=1846122&r2=1846123&view=diff
==============================================================================
--- spamassassin/trunk/UPGRADE (original)
+++ spamassassin/trunk/UPGRADE Thu Nov 8 10:53:46 2018
@@ -76,6 +76,8 @@ Note for Users Upgrading to SpamAssassin
- New dns_block_rule option handles blocked DNSBLs
+- New AuthRes module to process Authentication-Results headers (unfinished)
+
Note for Users Upgrading to SpamAssassin 3.4.2
----------------------------------------------
Added: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AuthRes.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AuthRes.pm?rev=1846123&view=auto
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AuthRes.pm (added)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AuthRes.pm Thu Nov 8 10:53:46 2018
@@ -0,0 +1,536 @@
+# <@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::AuthRes - use Authentication-Results header fields
+
+=head1 SYNOPSIS
+
+=head2 SpamAssassin configuration:
+
+loadplugin Mail::SpamAssassin::Plugin::AuthRes
+
+=head1 DESCRIPTION
+
+This plugin parses Authentication-Results header fields and can supply the
+results obtained to other plugins, so as to avoid repeating checks that have
+been performed already.
+
+=cut
+
+package Mail::SpamAssassin::Plugin::AuthRes;
+
+use Mail::SpamAssassin::Plugin;
+use Mail::SpamAssassin::Logger;
+use strict;
+use warnings;
+# use bytes;
+use re 'taint';
+
+our @ISA = qw(Mail::SpamAssassin::Plugin);
+
+# list of valid methods and values
+# https://www.iana.org/assignments/email-auth/email-auth.xhtml
+my %method_result = (
+ 'auth' => {'fail'=>1,'none'=>1,'pass'=>1,'permerror'=>1,'temperror'=>1},
+ 'dkim' => {'fail'=>1,'neutral'=>1,'none'=>1,'pass'=>1,'permerror'=>1,'policy'=>1,'temperror'=>1},
+ 'dkim-adsp' => {'discard'=>1,'fail'=>1,'none'=>1,'nxdomain'=>1,'pass'=>1,'permerror'=>1,'temperror'=>1,'unknown'=>1},
+ 'dkim-atps' => {'fail'=>1,'none'=>1,'pass'=>1,'permerror'=>1,'temperror'=>1},
+ 'dmarc' => {'fail'=>1,'none'=>1,'pass'=>1,'permerror'=>1,'temperror'=>1},
+ 'domainkeys' => {'fail'=>1,'neutral'=>1,'none'=>1,'permerror'=>1,'policy'=>1,'pass'=>1,'temperror'=>1},
+ 'iprev' => {'fail'=>1,'pass'=>1,'permerror'=>1,'temperror'=>1},
+ 'rrvs' => {'fail'=>1,'none'=>1,'pass'=>1,'permerror'=>1,'temperror'=>1,'unknown'=>1},
+ 'sender-id' => {'fail'=>1,'hardfail'=>1,'neutral'=>1,'none'=>1,'pass'=>1,'permerror'=>1,'policy'=>1,'softfail'=>1,'temperror'=>1},
+ 'smime' => {'fail'=>1,'neutral'=>1,'none'=>1,'pass'=>1,'permerror'=>1,'policy'=>1,'temperror'=>1},
+ 'spf' => {'fail'=>1,'hardfail'=>1,'neutral'=>1,'none'=>1,'pass'=>1,'permerror'=>1,'policy'=>1,'softfail'=>1,'temperror'=>1},
+ 'vbr' => {'fail'=>1,'none'=>1,'pass'=>1,'permerror'=>1,'temperror'=>1},
+);
+my %method_ptype_prop = (
+ 'auth' => {'smtp' => {'auth'=>1,'mailfrom'=>1}},
+ 'dkim' => {'header' => {'d'=>1,'i'=>1,'b'=>1}},
+ 'dkim-adsp' => {'header' => {'from'=>1}},
+ 'dkim-atps' => {'header' => {'from'=>1}},
+ 'dmarc' => {'header' => {'from'=>1}},
+ 'domainkeys' => {'header' => {'d'=>1,'from'=>1,'sender'=>1}},
+ 'iprev' => {'policy' => {'iprev'=>1}},
+ 'rrvs' => {'smtp' => {'rcptto'=>1}},
+ 'sender-id' => {'header' => {'*'=>1}},
+ 'smime' => {'body' => {'smime-part'=>1,'smime-identifer'=>1,'smime-serial'=>1,'smime-issuer'=>1}},
+ 'spf' => {'smtp' => {'mailfrom'=>1,'helo'=>1}},
+ 'vbr' => {'header' => {'md'=>1,'mv'=>1}},
+);
+
+# Some MIME helpers
+my $QUOTED_STRING = qr/"((?:[^"\\]++|\\.)*+)"?/;
+my $TOKEN = qr/[^\s\x00-\x1f\x80-\xff\(\)\<\>\@\,\;\:\/\[\]\?\=\"]+/;
+my $ATOM = qr/[a-zA-Z0-9\@\!\#\$\%\&\\\'\*\+\-\/\=\?\^\_\`\{\|\}\~]+/;
+
+sub new {
+ my ($class, $mailsa) = @_;
+
+ # the usual perlobj boilerplate to create a subclass object
+ $class = ref($class) || $class;
+ my $self = $class->SUPER::new($mailsa);
+ bless ($self, $class);
+
+ $self->set_config($mailsa->{conf});
+
+ # process first as other plugins might depend on us
+ $self->register_method_priority("parsed_metadata", -10);
+
+ $self->register_eval_rule("check_authres_result");
+
+ return $self;
+}
+
+sub set_config {
+ my ($self, $conf) = @_;
+ my @cmds;
+
+=head1 ADMINISTRATOR OPTIONS
+
+=over
+
+=item authres_networks internal/trusted/all (default: internal)
+
+Process Authenticated-Results headers set by servers from these networks
+(refers to SpamAssassin *_networks zones). Any header outside this is
+completely ignored and affects any module settings.
+
+ internal = internal_networks
+ trusted = internal_networks + trusted_networks
+ all = all above + all external
+
+Setting "all" makes sense only if your MX servers filter properly all
+incoming A-R headers. Even then it might be safer to just extend SA
+trusted_networks to any external servers whose A-R you want to see, and use
+the "trusted" setting.
+
+=cut
+
+ push (@cmds, {
+ setting => 'authres_networks',
+ is_admin => 1,
+ default => 'internal',
+ type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
+ code => sub {
+ my ($self, $key, $value, $line) = @_;
+ if (!defined $value || $value =~ /^$/) {
+ return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
+ }
+ $value = lc($value);
+ if ($value =~ /^(?:internal|trusted|all)$/) {
+ $self->{authres_networks} = $value;
+ } else {
+ return $Mail::SpamAssassin::Conf::INVALID_VALUE;
+ }
+ }
+ });
+
+=item authres_ignored_authserv authservid1 id2 ... (default: none)
+
+Ignored authentication server IDs (the domain-name-like first word of
+Authentication-Results field, also known as C<authserv-id>).
+
+Any A-R header is ignored if match is found.
+
+=cut
+
+ push (@cmds, {
+ setting => 'authres_ignored_authserv',
+ is_admin => 1,
+ default => {},
+ type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE,
+ code => sub {
+ my ($self, $key, $value, $line) = @_;
+ if (!defined $value || $value =~ /^$/) {
+ return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
+ }
+ foreach my $id (split(/\s+/, lc $value)) {
+ $self->{authres_ignored_authserv}->{$id} = 1;
+ }
+ }
+ });
+
+=item authres_trusted_authserv authservid1 id2 ... (default: none)
+
+Trusted authentication server IDs (the domain-name-like first word of
+Authentication-Results field, also known as C<authserv-id>).
+
+Note that if set, ALL A-R headers are ignored unless a match is found.
+
+=back
+
+=cut
+
+ push (@cmds, {
+ setting => 'authres_trusted_authserv',
+ is_admin => 1,
+ default => {},
+ type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE,
+ code => sub {
+ my ($self, $key, $value, $line) = @_;
+ if (!defined $value || $value =~ /^$/) {
+ return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
+ }
+ foreach my $id (split(/\s+/, lc $value)) {
+ $self->{authres_trusted_authserv}->{$id} = 1;
+ }
+ }
+ });
+
+ $conf->{parser}->register_commands(\@cmds);
+}
+
+=head1 METADATA
+
+Parsed headers are stored in $pms-E<gt>{authres_parsed}, as a hash of array
+of hashes where results are collected by method. For example, the header
+field:
+
+ Authentication-Results: server.example.com;
+ spf=pass smtp.mailfrom=bounce.example.org;
+ dkim=pass header.i=@example.org;
+ dkim=fail header.i=@another.signing.domain.example
+
+Produces the following structure:
+
+ $pms->{authres_parsed} = {
+ 'dkim' => [
+ {
+ 'properties' => {
+ 'header' => {
+ 'i' => '@example.org'
+ }
+ },
+ 'authserv' => 'server.example.com',
+ 'result' => 'pass',
+ 'version' => 1,
+ 'reason' => ''
+ },
+ {
+ 'properties' => {
+ 'header' => {
+ 'i' => '@another.signing.domain.example'
+ }
+ },
+ 'result' => 'fail',
+ 'authserv' => 'server.example.com',
+ 'version' => 1,
+ 'reason' => ''
+ },
+ ],
+ }
+
+Within each array, the order of results is the original, which should be most
+recent results first.
+
+For checking result of methods, $pms-E<gt>{authres_result} is available:
+
+ $pms->{authres_result} = {
+ 'dkim' => 'pass',
+ 'spf' => 'fail',
+ }
+
+=head1 EVAL FUNCTIONS
+
+=over 4
+
+=item header RULENAME eval:check_authres_result(method, result)
+
+Can be used to check results.
+
+ ifplugin Mail::SpamAssassin::Plugin::AuthRes
+ ifplugin !(Mail::SpamAssassin::Plugin::SPF)
+ header SPF_PASS eval:check_authres_result('spf', 'pass')
+ header SPF_FAIL eval:check_authres_result('spf', 'fail')
+ header SPF_SOFTFAIL eval:check_authres_result('spf', 'softfail')
+ header SPF_TEMPFAIL eval:check_authres_result('spf', 'tempfail')
+ endif
+ ifplugin !(Mail::SpamAssassin::Plugin::DKIM)
+ header DKIM_VERIFIED eval:check_authres_result('dkim', 'pass')
+ header DKIM_INVALID eval:check_authres_result('dkim', 'fail')
+ endif
+ endif
+
+=back
+
+=cut
+
+sub check_authres_result {
+ my ($self, $pms, $method, $wanted_result) = @_;
+
+ my $result = $pms->{authres_result}->{$method};
+ $wanted_result = lc($wanted_result);
+
+ if ($wanted_result eq 'missing') {
+ return !defined($result) ? 1 : 0;
+ }
+
+ return ($wanted_result eq $result);
+}
+
+sub parsed_metadata {
+ my ($self, $opts) = @_;
+
+ my $pms = $opts->{permsgstatus};
+
+ my @authres;
+ my $nethdr;
+
+ if ($pms->{conf}->{authres_networks} eq 'internal') {
+ $nethdr = 'ALL-INTERNAL';
+ } elsif ($pms->{conf}->{authres_networks} eq 'trusted') {
+ $nethdr = 'ALL-TRUSTED';
+ } else {
+ $nethdr = 'ALL';
+ }
+
+ foreach my $hdr (split(/^/m, $pms->get($nethdr))) {
+ if ($hdr =~ /^Authentication-Results:\s*(.+)/i) {
+ push @authres, $1;
+ }
+ }
+
+ if (!@authres) {
+ dbg("authres: no Authentication-Results headers found from %s",
+ $pms->{conf}->{authres_networks});
+ return 0;
+ }
+
+ foreach (@authres) {
+ eval {
+ $self->parse_authres($pms, $_);
+ } or do {
+ dbg("authres: skipping header, $@");
+ }
+ }
+
+ $pms->{authres_result} = {};
+ # Set $pms->{authres_result} info for all found methods
+ # 'pass' will always win if multiple results
+ foreach my $method (keys %method_result) {
+ my $parsed = $pms->{authres_parsed}->{$method};
+ next if !$parsed;
+ foreach my $pref (@$parsed) {
+ if (!$pms->{authres_result}->{$method} ||
+ $pref->{result} eq 'pass')
+ {
+ $pms->{authres_result}->{$method} = $pref->{result};
+ }
+ }
+ }
+
+ if (%{$pms->{authres_result}}) {
+ dbg("authres: results: %s",
+ join(' ', map { $_.'='.$pms->{authres_result}->{$_} }
+ sort keys %{$pms->{authres_result}}));
+ } else {
+ dbg("authres: no results");
+ }
+}
+
+sub parse_authres {
+ my ($self, $pms, $hdr) = @_;
+
+ dbg("authres: parsing Authentication-Results: $hdr");
+
+ my $authserv;
+ my $version = 1;
+ my @methods;
+
+ local $_ = $hdr;
+
+ # authserv-id
+ if (!/\G($TOKEN)/gcs) {
+ die("invalid authserv\n");
+ }
+ $authserv = lc($1);
+
+ if (%{$pms->{conf}->{authres_trusted_authserv}}) {
+ if (!$pms->{conf}->{authres_trusted_authserv}->{$authserv}) {
+ die("authserv not trusted: $authserv\n");
+ }
+ }
+ if ($pms->{conf}->{authres_ignored_authserv}->{$authserv}) {
+ die("ignored authserv: $authserv\n");
+ }
+
+ skip_cfws();
+ if (/\G\d+/gcs) { # skip authserv version
+ skip_cfws();
+ }
+ if (!/\G;/gcs) {
+ die("missing delimiter\n");
+ }
+ skip_cfws();
+
+ while (pos() < length()) {
+ my ($method, $result);
+ my $reason = '';
+ my $props = {};
+
+ # skip none method
+ if (/\Gnone\b/igcs) {
+ die("method none\n");
+ }
+
+ # method / version = result
+ if (!/\G([\w-]+)/gcs) {
+ die("invalid method\n");
+ }
+ $method = lc($1);
+ if (!exists $method_result{$method}) {
+ die("unknown method: $method\n");
+ }
+ skip_cfws();
+ if (/\G\//gcs) {
+ skip_cfws();
+ if (!/\G\d+/gcs) {
+ die("invalid $method version\n");
+ }
+ $version = $1;
+ skip_cfws();
+ }
+ if (!/\G=/gcs) {
+ die("missing result for $method: ".substr($_, pos())."\n");
+ }
+ skip_cfws();
+ if (!/\G(\w+)/gcs) {
+ die("invalid result for $method\n");
+ }
+ $result = $1;
+ if (!exists $method_result{$method}{$result}) {
+ die("unknown result for $method: $result\n");
+ }
+ skip_cfws();
+
+ # reason = value
+ if (/\Greason\b/igcs) {
+ skip_cfws();
+ if (!/\G=/gcs) {
+ die("invalid reason\n");
+ }
+ skip_cfws();
+ if (!/\G$QUOTED_STRING|($TOKEN)/gcs) {
+ die("invalid reason\n");
+ }
+ $reason = defined $1 ? $1 : $2;
+ skip_cfws();
+ }
+
+ # ptype.property = value
+ while (pos() < length()) {
+ my ($ptype, $property, $value);
+
+ # ptype
+ if (!/\G(\w+)/gcs) {
+ die("invalid ptype: ".substr($_,pos())."\n");
+ }
+ $ptype = lc($1);
+ if (!exists $method_ptype_prop{$method}{$ptype}) {
+ die("unknown ptype: $ptype\n");
+ }
+ skip_cfws();
+
+ # dot
+ if (!/\G\./gcs) {
+ die("missing property\n");
+ }
+ skip_cfws();
+
+ # property
+ if (!/\G(\w+)/gcs) {
+ die("invalid property\n");
+ }
+ $property = lc($1);
+ if (!exists $method_ptype_prop{$method}{$ptype}{$property} &&
+ !exists $method_ptype_prop{$method}{$ptype}{'*'}) {
+ die("unknown property for $ptype: $property\n");
+ }
+ skip_cfws();
+
+ # =
+ if (!/\G=/gcs) {
+ die("missing property value\n");
+ }
+ skip_cfws();
+
+ # value:
+ # The grammar is ( value / [ [ local-part ] "@" ] domain-name )
+ # where value := token / quoted-string
+ # and local-part := dot-atom / quoted-string / obs-local-part
+ if (!/\G$QUOTED_STRING|($ATOM(?:\.$ATOM)*|$TOKEN)(?=(?:[\s;]|$))/gcs) {
+ die("invalid $ptype.$property value\n");
+ }
+ $value = defined $1 ? $1 : $2;
+ skip_cfws();
+
+ $props->{$ptype}->{$property} = $value;
+
+ if (/\G(?:;|$)/gcs) {
+ skip_cfws();
+ last;
+ }
+ }
+
+ push @methods, [$method, {
+ 'authserv' => $authserv,
+ 'version' => $version,
+ 'result' => $result,
+ 'reason' => $reason,
+ 'properties' => $props,
+ }];
+ }
+
+ # paranoid check..
+ if (pos() < length()) {
+ die("parse ended prematurely?\n");
+ }
+
+ # Pushed to pms only if header parsed completely
+ foreach my $marr (@methods) {
+ push @{$pms->{authres_parsed}->{$marr->[0]}}, $marr->[1];
+ }
+
+ return 1;
+}
+
+# skip whitespace and comments
+sub skip_cfws {
+ /\G\s*/gcs;
+ if (/\G\(/gcs) {
+ my $i = 1;
+ while (/\G.*?([()]|\z)/gcs) {
+ $1 eq ')' ? $i-- : $i++;
+ last if !$i;
+ }
+ die("comment not ended\n") if $i;
+ /\G\s*/gcs;
+ }
+}
+
+#sub check_cleanup {
+# my ($self, $opts) = @_;
+# my $pms = $opts->{permsgstatus};
+# use Data::Dumper;
+# print STDERR Dumper($pms->{authres_parsed});
+# print STDERR Dumper($pms->{authres_result});
+#}
+
+1;
Modified: spamassassin/trunk/t/all_modules.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/all_modules.t?rev=1846123&r1=1846122&r2=1846123&view=diff
==============================================================================
--- spamassassin/trunk/t/all_modules.t (original)
+++ spamassassin/trunk/t/all_modules.t Thu Nov 8 10:53:46 2018
@@ -56,6 +56,7 @@ loadplugin Mail::SpamAssassin::Plugin::H
loadplugin Mail::SpamAssassin::Plugin::ResourceLimits
loadplugin Mail::SpamAssassin::Plugin::FromNameSpoof
loadplugin Mail::SpamAssassin::Plugin::Phishing
+loadplugin Mail::SpamAssassin::Plugin::AuthRes
");
tstprefs("
Added: spamassassin/trunk/t/authres.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/authres.t?rev=1846123&view=auto
==============================================================================
--- spamassassin/trunk/t/authres.t (added)
+++ spamassassin/trunk/t/authres.t Thu Nov 8 10:53:46 2018
@@ -0,0 +1,146 @@
+#!/usr/bin/perl
+
+use lib '.';
+use lib 't';
+use SATest;
+sa_t_init("authres");
+
+use Test::More;
+plan tests => 44;
+
+# ---------------------------------------------------------------------------
+
+tstpre ("
+loadplugin Mail::SpamAssassin::Plugin::AuthRes
+");
+
+## with internal networks
+
+tstprefs("
+clear_internal_networks
+clear_trusted_networks
+internal_networks 212.17.35.15
+trusted_networks 212.17.35.15
+trusted_networks 141.154.95.22
+");
+
+%patterns = (
+ 'parsing Authentication-Results: authrestest1int', 'hdr1',
+ 'parsing Authentication-Results: authrestest2int', 'hdr2',
+ 'parsing Authentication-Results: authrestest3int', 'hdr3',
+ 'parsing Authentication-Results: authrestest4int', 'hdr4',
+ 'parsing Authentication-Results: authrestest5int', 'hdr5',
+ 'parsing Authentication-Results: authrestest6int', 'hdr6',
+ 'authres: results: dkim=pass dmarc=none spf=pass', 'results',
+ );
+
+%anti_patterns = (
+ 'parsing Authentication-Results: authrestest7tru', 'hdr7',
+ 'parsing Authentication-Results: authrestest8ext', 'hdr8',
+ 'authres: no Authentication-Results headers found', 'nohdr',
+ 'authres: skipping header,', 'skipping',
+ );
+
+sarun ("-D authres -L -t < data/nice/authres 2>&1", \&patterns_run_cb);
+ok_all_patterns();
+
+
+## with trusted networks included
+
+tstprefs("
+clear_internal_networks
+clear_trusted_networks
+internal_networks 212.17.35.15
+trusted_networks 212.17.35.15
+trusted_networks 141.154.95.22
+
+authres_networks trusted
+");
+
+%patterns = (
+ 'parsing Authentication-Results: authrestest1int', 'hdr1',
+ 'parsing Authentication-Results: authrestest2int', 'hdr2',
+ 'parsing Authentication-Results: authrestest3int', 'hdr3',
+ 'parsing Authentication-Results: authrestest4int', 'hdr4',
+ 'parsing Authentication-Results: authrestest5int', 'hdr5',
+ 'parsing Authentication-Results: authrestest6int', 'hdr6',
+ 'parsing Authentication-Results: authrestest7tru', 'hdr7',
+ 'authres: results: dkim=pass dmarc=none spf=pass', 'results',
+ );
+
+%anti_patterns = (
+ 'parsing Authentication-Results: authrestest8ext', 'hdr8',
+ 'authres: no Authentication-Results headers found', 'nohdr',
+ 'authres: skipping header,', 'skipping',
+ );
+
+sarun ("-D authres -L -t < data/nice/authres 2>&1", \&patterns_run_cb);
+ok_all_patterns();
+
+
+## with all networks (test ignore also)
+
+tstprefs("
+clear_internal_networks
+clear_trusted_networks
+internal_networks 212.17.35.15
+trusted_networks 212.17.35.15
+trusted_networks 141.154.95.22
+
+authres_networks all
+authres_ignored_authserv authrestest3int authrestest4int
+");
+
+%patterns = (
+ 'parsing Authentication-Results: authrestest1int', 'hdr1',
+ 'parsing Authentication-Results: authrestest2int', 'hdr2',
+ 'parsing Authentication-Results: authrestest3int', 'hdr3',
+ 'parsing Authentication-Results: authrestest4int', 'hdr4',
+ 'parsing Authentication-Results: authrestest5int', 'hdr5',
+ 'parsing Authentication-Results: authrestest6int', 'hdr6',
+ 'parsing Authentication-Results: authrestest7tru', 'hdr7',
+ 'parsing Authentication-Results: authrestest8ext', 'hdr8',
+ 'authres: results: dkim=pass dmarc=none spf=pass', 'results',
+ 'authres: skipping header, ignored authserv: authrestest3int', 'skip3',
+ 'authres: skipping header, ignored authserv: authrestest4int', 'skip4',
+ );
+
+%anti_patterns = (
+ 'authres: no Authentication-Results headers found', 'nohdr',
+ );
+
+sarun ("-D authres -L -t < data/nice/authres 2>&1", \&patterns_run_cb);
+ok_all_patterns();
+
+## with all networks (test trusted also)
+
+tstprefs("
+clear_internal_networks
+clear_trusted_networks
+internal_networks 212.17.35.15
+trusted_networks 212.17.35.15
+trusted_networks 141.154.95.22
+
+authres_networks all
+authres_trusted_authserv authrestest6int
+");
+
+%patterns = (
+ 'dbg: authres: skipping header, authserv not trusted: authrestest1int', 'skip1',
+ 'dbg: authres: skipping header, authserv not trusted: authrestest2int', 'skip2',
+ 'dbg: authres: skipping header, authserv not trusted: authrestest3int', 'skip3',
+ 'dbg: authres: skipping header, authserv not trusted: authrestest4int', 'skip4',
+ 'dbg: authres: skipping header, authserv not trusted: authrestest5int', 'skip5',
+ 'dbg: authres: skipping header, authserv not trusted: authrestest7tru', 'skip6',
+ 'dbg: authres: skipping header, authserv not trusted: authrestest8ext', 'skip7',
+ 'parsing Authentication-Results: authrestest6int', 'parsing',
+ 'authres: results: dkim=fail', 'results',
+ );
+
+%anti_patterns = (
+ 'authres: no Authentication-Results headers found', 'nohdr',
+ );
+
+sarun ("-D authres -L -t < data/nice/authres 2>&1", \&patterns_run_cb);
+ok_all_patterns();
+
Propchange: spamassassin/trunk/t/authres.t
------------------------------------------------------------------------------
svn:executable = *
Added: spamassassin/trunk/t/data/nice/authres
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/data/nice/authres?rev=1846123&view=auto
==============================================================================
--- spamassassin/trunk/t/data/nice/authres (added)
+++ spamassassin/trunk/t/data/nice/authres Thu Nov 8 10:53:46 2018
@@ -0,0 +1,99 @@
+From jm@dogma.slashnull.org Wed May 16 00:40:34 2001
+Return-Path: <jm...@dogma.slashnull.org>
+Delivered-To: jm@netnoteinc.com
+Received: from dogma.slashnull.org (dogma.slashnull.org [212.17.35.15]) by
+ mail.netnoteinc.com (Postfix) with ESMTP id 830E5115158 for
+ <jm...@netnoteinc.com>; Tue, 15 May 2001 23:40:33 +0000 (Eire)
+Authentication-Results: authrestest1int;
+ spf=pass smtp.mailfrom=bounce.example.org;
+ dkim=pass header.i=@example.org;
+ dkim=fail header.i=@another.signing.domain.example
+Authentication-Results: authrestest2int; dmarc=none (p=none dis=none) header.from=ximian.com
+authentication-Results: authrestest3int; spf=fail smtp.mailfrom=dogma.slashnull.org
+Authentication-Results: authrestest4int 2; spf=fail reason (BAH) = "just some (<>.%&! reason" smtp.mailfrom=dogma.slashnull.org
+Authentication-RESULTS: authrestest5int;
+ dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=SI+iqkld;
+Authentication-Results: authrestest6int;
+ dkim=fail (2048-bit key; unprotected) header.d=gmail.com header.i=" foo bar \"xyz\"@gmail.com" header.b=SI+iqkld;
+Received: (from jm@localhost) by dogma.slashnull.org (8.9.3/8.9.3) id
+ AAA30873 for jm@netnoteinc.com; Wed, 16 May 2001 00:40:33 +0100
+Received: from trna.ximian.com ([141.154.95.22]) by dogma.slashnull.org
+ (8.9.3/8.9.3) with ESMTP id AAA30867 for <jm...@jmason.org>;
+ Wed, 16 May 2001 00:40:31 +0100
+Authentication-Results: authrestest7tru; spf=fail smtp.mailfrom=last.trusted@example.com
+Received: from trna.ximian.com (IDENT:nobody@localhost [127.0.0.1]) by
+ trna.ximian.com (8.9.3/8.9.3) with ESMTP id SAA19408; Tue, 15 May 2001
+ 18:26:07 -0400
+Received: from milkplus (62-122-4-47.flat.galactica.it [62.122.4.47]) by
+ trna.ximian.com (8.9.3/8.9.3) with ESMTP id RAA19544; Tue, 15 May 2001
+ 17:31:24 -0400
+Received: by milkplus (Postfix, from userid 1000) id D3FDD10B051;
+ Tue, 15 May 2001 17:31:22 -0400 (EDT)
+Authentication-Results: authrestest8ext; spf=pass smtp.mailfrom=untrusted@example.com
+From: "Ximian, Inc." <ev...@ximian.com>
+To: announce@ximian.com
+Content-Type: text/plain
+X-Mailer: Evolution/0.10 (Preview Release)
+X-Loop: just so a test passes
+Date: 15 May 2001 17:31:22 -0400
+Message-Id: <98...@milkplus>
+MIME-Version: 1.0
+Subject: [HC Announce] Ximian Evolution 0.10 "Tasmanian Devil" is Now
+ Available!
+Sender: announce-admin@helixcode.com
+Errors-To: announce-admin@helixcode.com
+X-Mailman-Version: 1.1
+Precedence: bulk
+X-Hashcash: 0:040315:test@example.com:69781c87bae95c03
+X-hashcash: 1:20:040806:test1@example.com:test=foo:482b788d12eb9b56:2a3349
+List-Id: Announcements about Ximian. <announce.helixcode.com>
+X-Beenthere: announce@helixcode.com
+X-Spam-Status: No, hits=2 required=5
+
+A new preview release of Ximian Evolution is now available. Evolution
+is a personal and workgroup information management tool that seamlessly
+combines email, calendar, address book and more. Its extensive network
+support lets you connect to a wide range of services. Release 0.10
+includes a host of new features and fixes.
+
+TO GET THE EVOLUTION PREVIEW RELEASE
+
+- For those of you using Ximian GNOME, this version can be installed
+ by subscribing to the Evolution channel in Red Carpet (System -> Get
+ Software).
+
+- To download the preview release from the Ximian web site, go to:
+ http://www.ximian.com/apps/evolution-preview/index.php3
+
+TO GET SOURCE CODE
+
+You can also get the Evolution source tarball here:
+
+ ftp://ftp.gnome.org/pub/GNOME/unstable/sources/evolution
+
+ Evolution also requires Gal (0.7), GtkHTML (0.8.2), Bonobo (1.0),
+ OAF (0.6.2), GNOME VFS (1.0), libunicode (0.4.gnome), GNOME Print
+ (0.25) and ORBit (0.5.6).
+
+ ftp://ftp.gnome.org/pub/GNOME/unstable/sources/gal
+ ftp://ftp.gnome.org/pub/GNOME/unstable/sources/gtkhtml
+ ftp://ftp.gnome.org/pub/GNOME/unstable/sources/bonobo
+ ftp://ftp.gnome.org/pub/GNOME/unstable/sources/oaf
+ ftp://ftp.gnome.org/pub/GNOME/unstable/sources/gnome-vfs
+ ftp://ftp.gnome.org/pub/GNOME/unstable/sources/libunicode
+ ftp://ftp.gnome.org/pub/GNOME/stable/sources/gnome-print
+ ftp://ftp.gnome.org/pub/GNOME/stable/sources/ORBit
+
+TO VIEW 0.10 RELEASE NOTES
+
+The 0.10 release notes are available at:
+http://www.ximian.com/newsitems/evolution-0.10-announce.php3
+
+
+
+_______________________________________________
+Announce maillist - Announce@helixcode.com
+http://lists.helixcode.com/mailman/listinfo/announce
+
+
+