~ubuntu-branches/ubuntu/utopic/spamassassin/utopic-proposed

« back to all changes in this revision

Viewing changes to lib/Mail/SpamAssassin/Plugin/PhishTag.pm

  • Committer: Bazaar Package Importer
  • Author(s): Noah Meyerhans
  • Date: 2010-01-26 22:53:12 UTC
  • mfrom: (1.1.13 upstream) (5.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100126225312-wkftb10idc1kz2aq
Tags: 3.3.0-1
* New upstream version.
* Switch to dpkg-source 3.0 (quilt) format

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# <@LICENSE>
 
2
# Licensed to the Apache Software Foundation (ASF) under one or more
 
3
# contributor license agreements.  See the NOTICE file distributed with
 
4
# this work for additional information regarding copyright ownership.
 
5
# The ASF licenses this file to you under the Apache License, Version 2.0
 
6
# (the "License"); you may not use this file except in compliance with
 
7
# the License.  You may obtain a copy of the License at:
 
8
#
 
9
#     http://www.apache.org/licenses/LICENSE-2.0
 
10
#
 
11
# # Unless required by applicable law or agreed to in writing, software
 
12
# distributed under the License is distributed on an "AS IS" BASIS,
 
13
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
# See the License for the specific language governing permissions and
 
15
# limitations under the License.
 
16
# </@LICENSE>
 
17
#
 
18
###########################################################################
 
19
 
 
20
package Mail::SpamAssassin::Plugin::PhishTag;
 
21
 
 
22
use strict;
 
23
use warnings;
 
24
use Errno qw(EBADF);
 
25
use Mail::SpamAssassin;
 
26
use Mail::SpamAssassin::Logger;
 
27
 
 
28
use vars qw(@ISA);
 
29
 
 
30
our @ISA = qw(Mail::SpamAssassin::Plugin);
 
31
 
 
32
sub new{
 
33
  my ($class, $mailsa)=@_;
 
34
  $class=ref($class) ||$class;
 
35
  my $self = $class->SUPER::new($mailsa);
 
36
  bless($self,$class);
 
37
  $self->set_config($mailsa->{conf});
 
38
  return $self;
 
39
}
 
40
 
 
41
sub set_config{
 
42
  my($self, $conf) = @_;
 
43
  my @cmds = ();
 
44
 
 
45
  push (@cmds, {
 
46
    setting => 'trigger_target',
 
47
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE,
 
48
    is_admin => 1,
 
49
  });
 
50
 
 
51
  push (@cmds, {
 
52
    setting => 'trigger_config',
 
53
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
 
54
    is_admin => 1,
 
55
    default => '',
 
56
  });
 
57
 
 
58
  push (@cmds, {
 
59
    setting => 'trigger_ratio',
 
60
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC,
 
61
    is_admin => 1,
 
62
    default =>  0,
 
63
  });
 
64
 
 
65
  $conf->{parser}->register_commands(\@cmds);
 
66
}
 
67
 
 
68
#prepare the plugin
 
69
sub check_start{
 
70
  my ($self, $params) = @_;
 
71
  my $pms = $params->{permsgstatus};
 
72
  
 
73
  #initialize the PHISHTAG data structure for 
 
74
  #saving configuration information
 
75
  $pms->{PHISHTAG} = {};
 
76
  $pms->{PHISHTAG}->{triggers}={};
 
77
  $pms->{PHISHTAG}->{targets}=[];
 
78
 
 
79
  #read the configuration info
 
80
  $self->read_configfile($params);
 
81
  $self->read_settings($params);
 
82
}
 
83
 
 
84
sub read_settings{
 
85
  my ($self, $params) = @_;
 
86
  my $pms = $params->{permsgstatus};
 
87
 
 
88
  my $triggers= $pms->{PHISHTAG}->{triggers};
 
89
  my $targets= $pms->{PHISHTAG}->{targets};
 
90
  while (my ($tname,$ttarget)=each %{$pms->{conf}->{trigger_target}}){
 
91
      push @$targets, [$ttarget, $tname];
 
92
      $$triggers{$tname}=0;
 
93
  }
 
94
}
 
95
 
 
96
 
 
97
sub read_configfile{
 
98
  my ($self, $params) = @_;
 
99
  my $pms = $params->{permsgstatus};
 
100
 
 
101
  #nothing interesting here if there is not a configuration file
 
102
  return if($pms->{conf}->{trigger_config} !~/\S/);
 
103
 
 
104
  my $triggers= $pms->{PHISHTAG}->{triggers};
 
105
  my $targets= $pms->{PHISHTAG}->{targets};
 
106
 
 
107
  my $target;
 
108
  local *F;
 
109
  open(F, '<', $pms->{conf}->{trigger_config});
 
110
  for ($!=0; <F>; $!=0) {
 
111
      #each entry is separated by blank lines
 
112
      undef($target) if(!/\S/);
 
113
 
 
114
      #lines that start with pound are comments
 
115
      next if(/^\s*\#/);
 
116
 
 
117
      #an entry starts with a URL line prefixed with the word "target"
 
118
      if(/^target\s+(\S+)/){
 
119
          $target=[$1];
 
120
          push @$targets,$target;
 
121
      }
 
122
      #add the test to the list of listened triggers
 
123
      #and          to the triggers of the last target
 
124
      elsif(defined $target){
 
125
          s/\s+//g;
 
126
          $$triggers{$_}=0;
 
127
          push @$target, $_;
 
128
      }
 
129
  }
 
130
  defined $_ || $!==0  or
 
131
    $!==EBADF ? dbg("PHISHTAG: error reading config file: $!")
 
132
              : die "error reading config file: $!";
 
133
  close(F)  or die "error closing config file: $!";
 
134
}
 
135
 
 
136
sub hit_rule {
 
137
  my ($self, $params) = @_;
 
138
  my $pms = $params->{permsgstatus};
 
139
  my $rulename = $params->{rulename};
 
140
 
 
141
  #mark the rule as hit
 
142
  if(defined($pms->{PHISHTAG}->{triggers}->{$rulename})){
 
143
      $pms->{PHISHTAG}->{triggers}->{$rulename}=1;
 
144
      dbg("PHISHTAG: $rulename has been caught\n");
 
145
  }
 
146
}
 
147
 
 
148
sub check_post_learn {
 
149
  my ($self, $params) = @_;
 
150
  my $pms = $params->{permsgstatus};
 
151
 
 
152
  #find out which targets have fulfilled their requirements
 
153
  my $triggers= $pms->{PHISHTAG}->{triggers};
 
154
  my $targets= $pms->{PHISHTAG}->{targets};
 
155
  my @filled=();
 
156
  foreach my $target(@$targets){
 
157
      my $uri= $$target[0];
 
158
      my $fulfilled=1;
 
159
      #all the triggers of a target have to exist for it to be fulfilled
 
160
      foreach my $i(1..$#$target){
 
161
          if(! $triggers->{$$target[$i]}){
 
162
              $fulfilled=0;
 
163
              last;
 
164
          }
 
165
      }
 
166
      if($fulfilled){
 
167
          push @filled, $uri;
 
168
          dbg("PHISHTAG: Fulfilled $uri\n");
 
169
      }
 
170
  }
 
171
  
 
172
  if(scalar(@filled) &&
 
173
     $pms->{conf}->{trigger_ratio} > rand(100)){
 
174
      $pms->{PHISHTAG}->{letgo}=0;
 
175
      $pms->{PHISHTAG}->{uri}=$filled[int(rand(scalar(@filled)))];
 
176
      
 
177
      dbg("PHISHTAG: Decided to keep this email and point to ". 
 
178
          $pms->{PHISHTAG}->{uri});
 
179
      #make sure that SpamAssassin does not remove this email
 
180
      $pms->got_hit("PHISHTAG_TOSS", 
 
181
                    "BODY: ", 
 
182
                    score => -100);
 
183
  }
 
184
  else{
 
185
      dbg("PHISHTAG: Will let this email to SpamAssassin's discretion\n");
 
186
      $pms->{PHISHTAG}->{letgo}=1;
 
187
  }
 
188
  
 
189
 
 
190
  #nothing interesting here, if we will not rewrite the email
 
191
  if($pms->{PHISHTAG}->{letgo}){
 
192
      return;
 
193
  }
 
194
  
 
195
  my $pristine_body=\$pms->{msg}->{pristine_body};
 
196
  #dbg("PRISTINE>>\n".$$pristine_body);
 
197
 
 
198
  my $uris = $pms->get_uri_detail_list();
 
199
  #rewrite the url
 
200
  while (my($uri, $info) = each %{$uris}) { 
 
201
      if(defined ($info->{types}->{a})){
 
202
          $$pristine_body=~s/$uri/$pms->{PHISHTAG}->{uri}/mg;
 
203
      }
 
204
  }
 
205
  dbg("PRISTINE>>\n".$$pristine_body);
 
206
}
 
207
 
 
208
1;
 
209
__END__
 
210
 
 
211
=head1 NAME
 
212
 
 
213
PhishTag - SpamAssassin plugin for redirecting links in incoming emails.
 
214
 
 
215
=head1 SYNOPSIS
 
216
 
 
217
=over 4
 
218
 
 
219
    loadplugin     Mail::SpamAssassin::Plugin::PhishTag
 
220
 
 
221
    trigger_ratio    0.1
 
222
    trigger_target   RULE_NAME  http://www.antiphishing.org/consumer_recs.html
 
223
 
 
224
=back
 
225
    
 
226
=head1 DESCRIPTION
 
227
 
 
228
PhishTag enables administrators to rewrite links in emails that trigger certain
 
229
tests, preferably anti-phishing blacklist tests. The plugin will inhibit the
 
230
blocking of a portion of the emails that trigger the test by SpamAssassin, and
 
231
let them pass to the users' inbox after the rewrite. It is useful in providing
 
232
training to email users about company policies and general email usage.
 
233
 
 
234
=head1 OPTIONS
 
235
 
 
236
The following options can be set by modifying the configuration file.
 
237
 
 
238
=over 4
 
239
 
 
240
=item * trigger_ratio percentage_value
 
241
 
 
242
Sets the probability in percentage that a positive test will trigger the 
 
243
email rewrite, e.g. 0.1 will rewrite on the average 1 in 1000 emails that 
 
244
match the trigger.
 
245
 
 
246
=item * trigger_target RULE_NAME http_url
 
247
 
 
248
The name of the test which would trigger the email rewrite; all the URLs 
 
249
will be replaced by http_url.
 
250
 
 
251
=back
 
252
 
 
253
=head1 DOWNLOAD
 
254
 
 
255
The source of this plugin is avaliable at: 
 
256
http://umut.topkara.org/PhishTag/PhishTag.pm
 
257
a sample configuration file is also available:
 
258
http://umut.topkara.org/PhishTag/PhishTag.cf
 
259
 
 
260
=head1 SEE ALSO
 
261
 
 
262
Check the list of tests performed by SpamAssassin to modify the
 
263
configuration file to match your needs from 
 
264
http://spamassassin.apache.org/tests.html
 
265
 
 
266
=head1 AUTHOR
 
267
 
 
268
Umut Topkara, 2008, E<lt>umut@topkara.orgE<gt>
 
269
http://umut.topkara.org
 
270
 
 
271
=head1 COPYRIGHT AND LICENSE
 
272
 
 
273
This plugin is free software; you can redistribute it and/or modify
 
274
it under the same terms as SpamAssassin itself, either version 3.2.4 
 
275
or, at your option, any later version of SpamAssassin you may have 
 
276
available.
 
277
 
 
278
 
 
279
=cut