line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mail::Simple::DKIM::Signer;
|
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
21676
|
use strict;
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
45
|
|
4
|
1
|
|
|
1
|
|
6
|
use warnings;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
35
|
|
5
|
1
|
|
|
1
|
|
2457
|
use Digest::SHA qw/sha1/;
|
|
1
|
|
|
|
|
4154
|
|
|
1
|
|
|
|
|
86
|
|
6
|
1
|
|
|
1
|
|
896
|
use MIME::Base64;
|
|
1
|
|
|
|
|
734
|
|
|
1
|
|
|
|
|
70
|
|
7
|
1
|
|
|
1
|
|
889
|
use Crypt::OpenSSL::RSA;
|
|
1
|
|
|
|
|
10096
|
|
|
1
|
|
|
|
|
1041
|
|
8
|
|
|
|
|
|
|
our $VERSION = '0.01';
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub new {
|
12
|
|
|
|
|
|
|
|
13
|
0
|
|
|
0
|
0
|
|
my $class = shift;
|
14
|
0
|
|
|
|
|
|
my $options = shift;
|
15
|
0
|
|
|
|
|
|
my $self = {};
|
16
|
|
|
|
|
|
|
|
17
|
0
|
|
|
|
|
|
my $private_key = $options->{key};
|
18
|
0
|
|
|
|
|
|
$self->{headers} = $options->{headers};
|
19
|
|
|
|
|
|
|
|
20
|
0
|
|
|
|
|
|
my $rsa_priv = new_private_key Crypt::OpenSSL::RSA($private_key);
|
21
|
|
|
|
|
|
|
|
22
|
0
|
|
|
|
|
|
$self->{rsa} = $rsa_priv;
|
23
|
|
|
|
|
|
|
|
24
|
0
|
|
|
|
|
|
$self->{BodyCanonicalization} = 'simplebody';
|
25
|
0
|
|
|
|
|
|
$self->{HeadersCanonicalization} = 'simpleheader';
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
|
28
|
0
|
|
|
|
|
|
$self->{d} = $options->{domain};
|
29
|
|
|
|
|
|
|
|
30
|
0
|
|
0
|
|
|
|
$self->{s} = $options->{selector} || 'dkim';
|
31
|
|
|
|
|
|
|
|
32
|
0
|
|
0
|
|
|
|
$self->{c} = $options->{c} || 'simple/simple';
|
33
|
|
|
|
|
|
|
|
34
|
0
|
|
0
|
|
|
|
$self->{l} = $options->{l} || '0';
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
###get each methods
|
37
|
0
|
|
|
|
|
|
my @methods = split(/\//, $self->{c});
|
38
|
|
|
|
|
|
|
|
39
|
0
|
|
0
|
|
|
|
$self->{HeadersC} = $methods[0] || 'simple';
|
40
|
0
|
|
0
|
|
|
|
$self->{BodyC} = $methods[1] || 'simple';
|
41
|
|
|
|
|
|
|
|
42
|
0
|
|
0
|
|
|
|
$self->{a} = $options->{a} || 'rsa-sha1';
|
43
|
0
|
|
0
|
|
|
|
$self->{q} = $options->{q} || 'dns/txt';
|
44
|
|
|
|
|
|
|
|
45
|
0
|
|
|
|
|
|
$self->{i} = $options->{i};
|
46
|
|
|
|
|
|
|
|
47
|
0
|
|
|
|
|
|
return bless($self, $class);
|
48
|
|
|
|
|
|
|
}
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub sign {
|
53
|
|
|
|
|
|
|
|
54
|
0
|
|
|
0
|
0
|
|
my ($self,$headers,$body) =@_;
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
####convert body with simple Canonicalization
|
57
|
|
|
|
|
|
|
#$body = $self->SimpleBodyCanonicalization($body);
|
58
|
|
|
|
|
|
|
|
59
|
0
|
|
|
|
|
|
$body = $self->SimpleBodyCanonicalization($body);
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
##get body length
|
62
|
0
|
|
|
|
|
|
my $body_length = length($body);
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
####generate body ahsh key (bh)
|
65
|
0
|
|
|
|
|
|
my $bh = pack("H*", $body);
|
66
|
0
|
|
|
|
|
|
$bh = encode_base64(sha1($body));
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
###remove unwanted spaces from body hash
|
69
|
0
|
0
|
|
|
|
|
$bh =~ tr/\015\012 \t//d if defined $bh;
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
####start genrating signature of headers
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
##first run Canonicalization
|
75
|
0
|
|
|
|
|
|
$headers = SimpleHeaderCanonicalization($headers);
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
##add headers to array
|
78
|
0
|
|
|
|
|
|
my @headers = split(/\r\n/, $headers);
|
79
|
0
|
|
|
|
|
|
my @str;
|
80
|
|
|
|
|
|
|
my @headers_to_be_signed;
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
##loop throug headers
|
83
|
0
|
|
|
|
|
|
foreach my $header (@headers){
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
###remove embty leading and ending lines
|
86
|
0
|
|
|
|
|
|
$header = $self->trim($header);
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
##exlude headers with x- and dkim- part
|
89
|
0
|
0
|
|
|
|
|
push @headers_to_be_signed,$header if $header !~/^X-|^Dkim-/i;
|
90
|
|
|
|
|
|
|
#push @to_be_signed,$header;
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
##get name part of headers
|
93
|
0
|
|
|
|
|
|
$header =~ m/(.*?): (.*?)/;
|
94
|
0
|
0
|
|
|
|
|
push @str,$1 if $1 !~/^X-|^Dkim-/i;
|
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
}
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
###join header values we want to sign this will go to the h= tag
|
99
|
0
|
|
|
|
|
|
my $str = join(":",@str);
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
##getting i= tag
|
102
|
0
|
|
|
|
|
|
my $i_part = '';
|
103
|
0
|
|
|
|
|
|
my $l_part = '';
|
104
|
|
|
|
|
|
|
|
105
|
0
|
0
|
|
|
|
|
if ($self->{i}){
|
106
|
0
|
|
|
|
|
|
$i_part = " i=".$self->{i}.";";
|
107
|
|
|
|
|
|
|
}
|
108
|
|
|
|
|
|
|
|
109
|
0
|
0
|
|
|
|
|
if ($self->{l}){
|
110
|
0
|
|
|
|
|
|
$l_part = " l=$body_length;";
|
111
|
|
|
|
|
|
|
}
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
###create dkim string
|
114
|
0
|
|
|
|
|
|
my $dkim="v=1; a=$self->{a}; q=$self->{q};$l_part s=$self->{s};\r\n".
|
115
|
|
|
|
|
|
|
"\tc=$self->{c};\r\n".
|
116
|
|
|
|
|
|
|
"\th=$str;\r\n".
|
117
|
|
|
|
|
|
|
"\td=$self->{d};$i_part\r\n".
|
118
|
|
|
|
|
|
|
"\tbh=$bh;\r\n".
|
119
|
|
|
|
|
|
|
"\tb=";
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
##push dkim string to the headers_to_be_signed array
|
123
|
0
|
|
|
|
|
|
push (@headers_to_be_signed,"DKIM-Signature: ".$dkim);
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
##get headers to be signed as string
|
126
|
0
|
|
|
|
|
|
my $headers_to_be_signed = join("\r\n",@headers_to_be_signed);
|
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
##generate signature
|
130
|
0
|
|
|
|
|
|
my $signature = $self->{rsa}->sign($headers_to_be_signed);
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
##encode segnature
|
134
|
0
|
|
|
|
|
|
my $b = encode_base64($signature);
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
##remove unwanted new lines
|
137
|
0
|
0
|
|
|
|
|
$b =~ tr/\015\012 \t//d if defined $b;
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
###add signature to the dkim string
|
140
|
0
|
|
|
|
|
|
$dkim = $dkim.$b;
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
#return $dkim;
|
143
|
|
|
|
|
|
|
return {
|
144
|
0
|
|
|
|
|
|
string => "DKIM-Signature: ".$dkim,
|
145
|
|
|
|
|
|
|
value => $dkim,
|
146
|
|
|
|
|
|
|
key => "DKIM-Signature"
|
147
|
|
|
|
|
|
|
};
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
}
|
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub SimpleBodyCanonicalization {
|
156
|
|
|
|
|
|
|
|
157
|
0
|
|
|
0
|
0
|
|
my ($self,$body) = @_;
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
##convert \r\n to \n just in case if this came from windows
|
160
|
0
|
|
|
|
|
|
$body =~s /\r\n/\n/g;
|
161
|
|
|
|
|
|
|
|
162
|
0
|
|
|
|
|
|
$body =~s /\n/\r\n/g;
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
#$body = length($body);
|
165
|
0
|
|
|
|
|
|
my $bodylength = length($body);
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
###remove embty lines from the end of the message body
|
168
|
|
|
|
|
|
|
|
169
|
0
|
|
|
|
|
|
while (substr($body,$bodylength-4,4) =~ m/\r\n\r\n/){
|
170
|
0
|
|
|
|
|
|
$body = substr($body,0,length($body)-2);
|
171
|
|
|
|
|
|
|
}
|
172
|
|
|
|
|
|
|
|
173
|
0
|
|
|
|
|
|
return $body;
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
}
|
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub SimpleHeaderCanonicalization {
|
180
|
|
|
|
|
|
|
|
181
|
0
|
|
|
0
|
0
|
|
my $header =shift;
|
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
##convert \r\n to \n just in case if this came from windows
|
184
|
0
|
|
|
|
|
|
$header =~s /\r\n/\n/g;
|
185
|
0
|
|
|
|
|
|
$header =~s /\n/\r\n/g;
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
###nothing else to do with headers as this is what simple header Canonicalization
|
188
|
|
|
|
|
|
|
##documents say
|
189
|
|
|
|
|
|
|
|
190
|
0
|
|
|
|
|
|
return $header;
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
}
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub trim($) {
|
197
|
|
|
|
|
|
|
|
198
|
0
|
|
|
0
|
0
|
|
my ($self,$string) = @_;
|
199
|
|
|
|
|
|
|
|
200
|
0
|
|
|
|
|
|
$string =~ s/^\s+//;
|
201
|
0
|
|
|
|
|
|
$string =~ s/\s+$//;
|
202
|
|
|
|
|
|
|
|
203
|
0
|
|
|
|
|
|
return $string;
|
204
|
|
|
|
|
|
|
}
|
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
1;
|
209
|
|
|
|
|
|
|
__END__
|