File Coverage

blib/lib/Mail/SpamAssassin/Plugin/Konfidi.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             # <@LICENSE>
2             # Licensed under the Apache License, Version 2.0 (the "License");
3             # you may not use this file except in compliance with the License.
4             # You may obtain a copy of the License at
5             #
6             # http://www.apache.org/licenses/LICENSE-2.0
7             #
8             # Unless required by applicable law or agreed to in writing, software
9             # distributed under the License is distributed on an "AS IS" BASIS,
10             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11             # See the License for the specific language governing permissions and
12             # limitations under the License.
13             #
14              
15             package Mail::SpamAssassin::Plugin::Konfidi;
16              
17             =head1 NAME
18              
19             Mail::SpamAssassin::Plugin::Konfidi - A SpamAssassin plugin that uses the Konfidi distributed trust network for authenticated messages.
20              
21             =head1 VERSION
22              
23             Version 1.0.1
24              
25             =cut
26              
27             our $VERSION = '1.0.1';
28              
29             =head1 SYNOPSIS
30              
31             Install this module by running:
32              
33             cpan Mail::SpamAssassin::Plugin::Konfidi
34              
35             Tell SpamAssassin to use it by putting the following (from this module's F) in a configuration file
36              
37             loadplugin Mail::SpamAssassin::Plugin::Konfidi
38              
39             Configure the plugin by putting the following (from this module's F) in a configuration file (see L)
40              
41             ifplugin Mail::SpamAssassin::Plugin::Konfidi
42            
43             full KONFIDI_TRUST_VALUE eval:check_konfidi()
44             describe KONFIDI_TRUST_VALUE Konfidi-computed trust value for sender, if sender is authenticated
45            
46             endif # Mail::SpamAssassin::Plugin::Konfidi
47              
48             Set settings for yourself:
49              
50             konfidi_service_url http://test-server.konfidi.org/
51             konfidi_my_pgp_fingerprint 1234DEADBEEF5678... # this should be your full 40-digit fingerprint
52            
53             konfidi_rating0_becomes_score 0
54             konfidi_rating1_becomes_score -20
55              
56             The rating-becomes-score settings define a linear scale, so using the above example, a Konfidi rating of 0.75 would generate a SpamAssassin score of -15. You do not set any regular 'score' rules since the scores are assigned dynamically based on these settings.
57              
58             =head1 DESCRIPTION
59              
60             This plugin currently only uses OpenPGP signatures for authentication and requires L. Future versions will also support L and
61             L for authentication.
62              
63             The loadplugin statement for OpenPGP must occur before the loadplugin statement for Konfidi. This can be done by putting them in order in one file, or naming your configuration files in order like 26_openpgp.cf and 61_konfidi.cf
64              
65             For project information, see L
66              
67             =head1 USER SETTINGS
68              
69             If you want to add a header that shows the Konfidi trust value, use this:
70              
71             add_header all Konfidi-Trust-Value _KONFIDITRUSTVALUE_
72              
73             =cut
74              
75 2     2   302491 use warnings;
  2         6  
  2         98  
76 2     2   12 use strict;
  2         5  
  2         120  
77 2     2   1173 use Mail::SpamAssassin::Plugin;
  0            
  0            
78             use Mail::SpamAssassin::Logger;
79             use Mail::SpamAssassin::Timeout;
80             use Konfidi::Client;
81             use Error qw(:try);
82              
83             use vars qw(@ISA);
84             @ISA = qw(Mail::SpamAssassin::Plugin);
85              
86             sub new {
87             my $class = shift;
88             my $mailsaobject = shift;
89              
90             # some boilerplate...
91             $class = ref($class) || $class;
92             my $self = $class->SUPER::new($mailsaobject);
93             bless ($self, $class);
94              
95             dbg "konfidi: created";
96            
97             $self->register_eval_rule ("check_konfidi");
98            
99             $self->{konfidi_client} = Konfidi::Client->new();
100            
101             $self->set_config($mailsaobject->{conf});
102            
103             return $self;
104             }
105              
106             # SA 3.1 style of parsing config options
107             sub set_config {
108             my($self, $conf) = @_;
109             my @cmds = ();
110              
111             # see Mail::SpamAssassin::Conf::Parser for expected format of the "config blocks" stored in @cmds
112              
113             push(@cmds, {
114             setting => 'konfidi_service_url',
115             default => 'http://test-server.konfidi.org/',
116             type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
117             });
118             push(@cmds, {
119             setting => 'konfidi_my_pgp_fingerprint',
120             #default => 'http://test-server.konfidi.org/',
121             type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
122             });
123             #TODO: make this required
124             # TODO validate format
125             push(@cmds, {
126             setting => 'konfidi_rating1_becomes_score',
127             default => 0,
128             type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC,
129             });
130             push(@cmds, {
131             setting => 'konfidi_rating0_becomes_score',
132             default => 0,
133             type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC,
134             });
135            
136             # grr, why isn't register_commands documented?
137             $conf->{parser}->register_commands(\@cmds);
138            
139             # FIXME: validate that this gets set
140             $self->{konfidi_client}->server($conf->{konfidi_service_url});
141             }
142              
143             # see http://wiki.apache.org/spamassassin/PluginWritingTips "Writing plugins with dynamic score rules"
144             sub check_konfidi {
145             my ($self, $scan) = @_;
146             dbg "konfidi: running check_konfidi";
147             if ($scan->{openpgp_signed_good}) {
148             # FIXME: timeouts, ala http://wiki.apache.org/spamassassin/iXhash
149             my $kr;
150             try {
151             $kr = $self->{konfidi_client}->query($scan->{conf}->{konfidi_my_pgp_fingerprint}, $scan->{openpgp_fingerprint}, 'http://www.konfidi.org/ns/topics/0.0#internet-communication');
152             dbg "konfidi: response value: " . $kr->{'Rating'};
153             } catch Konfidi::Client::Error with {
154             my $E = shift;
155             dbg "konfidi: couldn't query the trustserver: $E";
156             # for some reason this doesn't exit the sub???
157             return 0;
158             };
159             return 0 unless $kr;
160            
161             # convert [0,1] rating to SA score
162             my $score = $scan->{conf}->{konfidi_rating0_becomes_score} - $kr->{'Rating'} *
163             ($scan->{conf}->{konfidi_rating0_becomes_score} - $scan->{conf}->{konfidi_rating1_becomes_score});
164             dbg "konfidi: scoring " . sprintf("%0.3f", $score);
165            
166             # http://wiki.apache.org/spamassassin/PluginWritingTips dynamic score rules
167             $scan->got_hit("KONFIDI_TRUST_VALUE", "KONFIDI: ", ruletype => 'eval', score => $score);
168             for my $set (0..3) {
169             $scan->{conf}->{scoreset}->[$set]->{"KONFIDI_TRUST_VALUE"} = sprintf("%0.3f", $score);
170             }
171             # "KONFIDI" as $area?
172              
173             # Mail::SpamAssassin::Plugin::AWL 3.1.7 line 387
174             # $scan->_handle_hit("KONFIDI_TRUST_VALUE", $score, "KONFIDI: ", $scan->{conf}->{descriptions}->{KONFIDI_TRUST_VALUE});
175              
176             $scan->set_tag("KONFIDITRUSTVALUE", $kr->{'Rating'});
177              
178             } else {
179             dbg "konfidi: skipping message, did not have a good PGP signature (make sure Mail::SpamAssassin::Plugin::OpenPGP is in use)";
180             }
181             return 0;
182             }
183              
184             # http://mail-archives.apache.org/mod_mbox/spamassassin-dev/200707.mbox/%3c46AFF6EC.3090404@brondsema.net%3e
185             #~ sub parsed_metadata {
186             #~ my ($self, $opts) = @_;
187             #~ return if $self->{main}->{local_tests_only};
188              
189             #~ my $scan = $opts->{permsgstatus} or die "No scanner!";
190             #~ dbg "konfidi: parsed_metadata: " . $scan->{openpgp_signed};
191             #~ #$self->_karma_send($scanner);
192              
193             #~ return undef;
194             #~ }
195              
196             #~ # "This is a good place to harvest your own asynchronously-started network lookups."
197             #~ # http://search.cpan.org/~shevek/Mail-Karmasphere-Client-2.10/lib/Mail/SpamAssassin/Plugin/Karmasphere.pm#INTERNALS
198             #~ sub check_post_dnsbl {
199             #~ my ($self, $opts) = @_;
200             #~ return if $self->{main}->{local_tests_only};
201              
202             #~ my $scan = $opts->{permsgstatus} or die "No scanner!";
203             #~ dbg "konfidi: check_post_dnsbl: " . $scan->{openpgp_signed};
204             #~ }
205              
206             1; # End of Mail::SpamAssassin::Plugin::Konfidi
207             __END__