File Coverage

blib/lib/Mail/DomainKeys/Key/Public.pm
Criterion Covered Total %
statement 68 107 63.5
branch 19 56 33.9
condition 1 4 25.0
subroutine 10 16 62.5
pod 0 12 0.0
total 98 195 50.2


line stmt bran cond sub pod time code
1             # Copyright (c) 2004 Anthony D. Urso. All rights reserved.
2             # This program is free software; you can redistribute it and/or
3             # modify it under the same terms as Perl itself.
4              
5             package Mail::DomainKeys::Key::Public;
6              
7 8     8   26309 use base "Mail::DomainKeys::Key";
  8         17  
  8         8616  
8              
9 8     8   52 use strict;
  8         14  
  8         5109  
10              
11             our $VERSION = "0.88";
12              
13             sub new {
14 6     6 0 108 my $type = shift;
15 6         22 my %prms = @_;
16              
17 6         17 my $self = {};
18              
19 6         23 $self->{'GRAN'} = $prms{'Granularity'};
20 6         20 $self->{'NOTE'} = $prms{'Note'};
21 6         18 $self->{'TEST'} = $prms{'Testing'};
22 6   50     173 $self->{'TYPE'} = ($prms{'Type'} or "rsa");
23 6         20 $self->{'DATA'} = $prms{'Data'};
24              
25 6         33 bless $self, $type;
26             }
27              
28             sub load {
29 0     0 0 0 my $type = shift;
30 0         0 my %prms = @_;
31              
32 0         0 my $self = {};
33              
34              
35 0         0 $self->{'GRAN'} = $prms{'Granularity'};
36 0         0 $self->{'NOTE'} = $prms{'Note'};
37 0         0 $self->{'TEST'} = $prms{'Testing'};
38 0   0     0 $self->{'TYPE'} = ($prms{'Type'} or "rsa");
39              
40 0 0       0 if ($prms{'File'}) {
41 0         0 my @data;
42 0 0       0 open FILE, "<$prms{'File'}" or
43             return;
44 0         0 while () {
45 0         0 chomp;
46 0 0       0 /^---/ and
47             next;
48 0         0 push @data, $_;
49             }
50 0         0 $self->{'DATA'} = join '', @data;
51             } else {
52 0         0 return;
53             }
54              
55 0         0 bless $self, $type;
56             }
57              
58             sub fetch {
59 8     8   16966 use Net::DNS;
  8         1606464  
  8         7864  
60              
61 1     1 0 46 my $type = shift;
62 1         7 my %prms = @_;
63              
64 1         2 my $strn;
65              
66              
67 1 50       4 ($prms{'Protocol'} eq "dns") or
68             return;
69              
70 1         6 my $host = $prms{'Selector'} . "._domainkey." . $prms{'Domain'};
71              
72 1 50       21 my $rslv = new Net::DNS::Resolver or
73             return;
74            
75 1 50       821 my $resp = $rslv->query($host, "TXT") or
76             return;
77              
78 1         50579 foreach my $ans ($resp->answer) {
79 1 50       14 next unless $ans->type eq "TXT";
80 1         23 $strn = join "", $ans->char_str_list;
81             }
82              
83             $strn or
84 1 50       60 return;
85              
86 1 50       5 my $self = &parse_string($strn) or
87             return;
88              
89 1         45 bless $self, $type;
90             }
91              
92             sub parse {
93 0     0 0 0 my $type = shift;
94 0         0 my %prms = @_;
95              
96              
97 0 0       0 my $self = &parse_string($prms{'String'}) or
98             return;
99              
100 0         0 bless $self, $type;
101             }
102              
103             sub as_string {
104 0     0 0 0 my $self = shift;
105              
106 0         0 my $text;
107              
108              
109 0 0       0 $self->granularity and
110             $text .= "g=" . $self->granularity . "; ";
111            
112 0 0       0 $self->type and
113             $text .= "k=" . $self->type . "; ";
114              
115 0 0       0 $self->note and
116             $text .= "n=" . $self->note . "; ";
117            
118 0 0       0 $self->testing and
119             $text .= "t=y; ";
120              
121 0         0 $text .= "p=" . $self->data;
122            
123 0 0       0 length $text and
124             return $text;
125              
126 0         0 return;
127             }
128              
129             sub convert {
130 8     8   21256 use Crypt::OpenSSL::RSA;
  8         88757  
  8         13058  
131              
132 7     7 0 17 my $self = shift;
133              
134              
135 7 50       102 $self->data or
136             return;
137              
138             # have to PKCS1ify the pubkey because openssl is too finicky...
139 7         22 my $cert = "-----BEGIN PUBLIC KEY-----\n";
140              
141 7         47 for (my $i = 0; $i < length $self->data; $i += 64) {
142 22         64 $cert .= substr $self->data, $i, 64;
143 22         97 $cert .= "\n";
144             }
145              
146 7         25 $cert .= "-----END PUBLIC KEY-----\n";
147              
148 7         14 my $cork;
149            
150 7         14 eval {
151 7         112 $cork = new_public_key Crypt::OpenSSL::RSA($cert);
152             };
153              
154 7 50       8280 $@ and
155             $self->errorstr($@),
156             return;
157              
158 7 50       82 $cork or
159             return;
160              
161             # segfaults on my machine
162             # $cork->check_key or
163             # return;
164              
165 7         120 $self->cork($cork);
166              
167 7         186 return 1;
168             }
169              
170             sub verify {
171 6     6 0 30 my $self = shift;
172 6         25 my %prms = @_;
173              
174              
175 6         13 my $rtrn = eval {
176 6         36 $self->cork->verify($prms{'Text'}, $prms{'Signature'});
177             };
178              
179 6 50       32 $@ and
180             $self->errorstr($@),
181             return;
182            
183 6         55 return $rtrn;
184             }
185              
186             sub granularity {
187 6     6 0 16 my $self = shift;
188              
189 6 50       34 (@_) and
190             $self->{'GRAN'} = shift;
191              
192 6         42 $self->{'GRAN'};
193             }
194              
195             sub note {
196 0     0 0 0 my $self = shift;
197              
198 0 0       0 (@_) and
199             $self->{'NOTE'} = shift;
200              
201 0         0 $self->{'NOTE'};
202             }
203              
204             sub revoked {
205 0     0 0 0 my $self = shift;
206              
207 0 0       0 $self->data or
208             return 1;
209              
210 0         0 return;
211             }
212              
213             sub testing {
214 0     0 0 0 my $self = shift;
215              
216 0 0       0 (@_) and
217             $self->{'TEST'} = shift;
218              
219 0         0 $self->{'TEST'};
220             }
221              
222             sub parse_string {
223 1     1 0 3 my $text = shift;
224              
225 1         2 my %tags;
226              
227              
228 1         10 foreach my $tag (split /;/, $text) {
229 3         54 $tag =~ s/^\s*|\s*$//g;
230              
231 3         7 foreach ($tag) {
232 3 50       8 /^g=(\S+)$/ and
233             $tags{'GRAN'} = $1;
234 3 100       22 /^k=(rsa)$/i and
235             $tags{'TYPE'} = lc $1;
236 3 100       11 /^n=(.*)$/ and
237             $tags{'NOTE'} = $1;
238 3 100       14 /^p=([A-Za-z0-9\+\/\=]+)$/ and
239             $tags{'DATA'} = $1;
240 3 50       12 /^t=y$/i and
241             $tags{'TEST'} = 1;
242             }
243             }
244              
245 1         5 return \%tags;
246             }
247              
248             1;