File Coverage

blib/lib/Mail/SRS/Shortcut.pm
Criterion Covered Total %
statement 27 31 87.1
branch 6 10 60.0
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 42 50 84.0


line stmt bran cond sub pod time code
1             package Mail::SRS::Shortcut;
2              
3 8     8   20625 use strict;
  8         15  
  8         231  
4 8     8   39 use warnings;
  8         11  
  8         196  
5 8     8   36 use vars qw(@ISA);
  8         19  
  8         277  
6 8     8   38 use Carp;
  8         13  
  8         478  
7 8     8   595 use Mail::SRS qw(:all);
  8         14  
  8         4070  
8              
9             @ISA = qw(Mail::SRS);
10              
11             =head1 NAME
12              
13             Mail::SRS::Shortcut - A shortcutting Sender Rewriting Scheme
14              
15             =head1 SYNOPSIS
16              
17             use Mail::SRS::Shortcut;
18             my $srs = new Mail::SRS::Shortcut(...);
19              
20             =head1 DESCRIPTION
21              
22             WARNING: Using the simple Shortcut strategy is a very bad idea. Use the
23             Guarded strategy instead. The weakness in the Shortcut strategy is
24             documented at http://www.anarres.org/projects/srs/
25              
26             See Mail::SRS for details of the standard SRS subclass interface.
27             This module provides the methods compile() and parse(). It operates
28             without store, and shortcuts around all middleman resenders.
29              
30             =head1 SEE ALSO
31              
32             L
33              
34             =cut
35              
36             sub compile {
37 64     64 1 116 my ($self, $sendhost, $senduser) = @_;
38              
39 64 100       394 if ($senduser =~ s/^$SRS0RE//io) {
    50          
40             # This duplicates effort in Guarded.pm but makes this file work
41             # standalone.
42             # We just do the split because this was hashed with someone
43             # else's secret key and we can't check it.
44             # hash, timestamp, host, user
45 16         161 (undef, undef, $sendhost, $senduser) =
46             split(qr/\Q$SRSSEP\E/, $senduser, 4);
47             # We should do a sanity check. After all, it might NOT be
48             # an SRS address, unlikely though that is. We are in the
49             # presence of malicious agents. However, this code is
50             # never reached if the Guarded subclass is used.
51             }
52             elsif ($senduser =~ s/$SRS1RE//io) {
53             # This should never be hit in practice. It would be bad.
54             # Introduce compatibility with the guarded format?
55             # SRSHOST, hash, timestamp, host, user
56 0         0 (undef, undef, undef, $sendhost, $senduser) =
57             split(qr/\Q$SRSSEP\E/, $senduser, 6);
58             }
59              
60 64         240 my $timestamp = $self->timestamp_create();
61              
62 64         200 my $hash = $self->hash_create($timestamp, $sendhost, $senduser);
63              
64             # Note that there are 5 fields here and that sendhost may
65             # not contain a valid separator. Therefore, we do not need to
66             # escape separators anywhere in order to reverse this
67             # transformation.
68 64         701 return $SRS0TAG . $self->separator .
69             join($SRSSEP, $hash, $timestamp, $sendhost, $senduser);
70             }
71              
72             sub parse {
73 95     95 1 144 my ($self, $user) = @_;
74              
75 95 50       425 unless ($user =~ s/$SRS0RE//oi) {
76             # We should deal with SRS1 addresses here, just in case?
77 0         0 die "Reverse address does not match $SRS0RE.";
78             }
79              
80             # The 4 here matches the number of fields we encoded above. If
81             # there are more separators, then they belong in senduser anyway.
82 95         739 my ($hash, $timestamp, $sendhost, $senduser) =
83             split(qr/\Q$SRSSEP\E/, $user, 4);
84             # Again, this must match as above.
85 95 50       385 unless ($self->hash_verify($hash,$timestamp,$sendhost,$senduser)) {
86 0         0 die "Invalid hash";
87             }
88              
89 95 50       916 unless ($self->timestamp_check($timestamp)) {
90 0         0 die "Invalid timestamp";
91             }
92              
93 95         333 return ($sendhost, $senduser);
94             }
95              
96             1;