File Coverage

lib/Net/Domain/TMCH.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             # Copyrights 2013-2015 by [Mark Overmeer].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5 3     3   1663169 use warnings;
  3         10  
  3         115  
6 3     3   86 use strict;
  3         9  
  3         131  
7              
8             package Net::Domain::TMCH;
9 3     3   33 use vars '$VERSION';
  3         11  
  3         232  
10             $VERSION = '0.18';
11              
12 3     3   20 use base 'Exporter';
  3         7  
  3         351  
13              
14 3     3   1455 use Log::Report 'net-domain-smd';
  3         226737  
  3         27  
15              
16 3     3   2330 use Net::Domain::SMD::Schema ();
  0            
  0            
17             use Net::Domain::TMCH::CRL ();
18             use Net::Domain::SMD::RL ();
19              
20             use Crypt::OpenSSL::VerifyX509 ();
21             use Crypt::OpenSSL::X509 qw(FORMAT_ASN1 FORMAT_PEM);
22             use File::Basename qw(dirname);
23             use File::Spec::Functions qw(catfile);
24             use Scalar::Util qw(blessed);
25             use URI ();
26              
27             use constant
28             { TMV_CRL_LIVE => 'http://crl.icann.org/tmch.crl' # what? no https?
29             , TMV_CRL_PILOT => 'http://crl.icann.org/tmch_pilot.crl'
30             };
31              
32             sub icannCert($) { catfile dirname(__FILE__), 'TMCH', 'icann', "$_[1].pem" }
33              
34              
35             sub new($%) { my ($class, %args) = @_; (bless {}, $class)->init(\%args) }
36              
37             sub init($)
38             { my ($self, $args) = @_;
39              
40             my $tmv = $args->{tmv_certificate};
41             if($tmv && !(blessed $tmv && $tmv->isa('Crypt::OpenSSL::X509')))
42             { my $read = eval { Crypt::OpenSSL::X509->new_from_file($tmv) };
43             $@ and error __x"cannot read certificate from {file}: {err}"
44             , file => $tmv, err => $@;
45             $tmv = $read;
46             }
47              
48             $self->{NDT_smds} = $args->{smds_admin} ||
49             Net::Domain::SMD::Schema->new
50             ( auto_datetime => $args->{auto_datetime}
51             , tmv_certificate => $tmv
52             );
53              
54             my $pilot = $self->{NDT_pilot} = $args->{is_pilot};
55             my $stage = $pilot ? 'tmch_pilot' : 'tmch';
56             my $tmch_pem = $args->{tmch_certificate} || $self->icannCert($stage);
57              
58             # user will not understand the errors from module ::X509
59             use filetest 'access';
60             -r $tmch_pem
61             or error __x"cannot read PEM from {fn}", fn => $tmch_pem;
62              
63             $self->{NDT_tmch_cert} = Crypt::OpenSSL::X509->new_from_file($tmch_pem);
64             $self->{NDT_tmch_ca} = Crypt::OpenSSL::VerifyX509->new($tmch_pem);
65             $self->{NDT_smdrl} = [ $self->_smdrl($args->{smd_revocations}) ];
66             $self->{NDT_crl} = $self->_crl($args->{cert_revocations}
67             || ($pilot ? TMV_CRL_PILOT : TMV_CRL_LIVE));
68              
69             $self;
70             }
71              
72             sub _crl($)
73             { my ($self, $r) = @_;
74              
75             $r = URI->new($r)
76             if !blessed $r && $r =~ m!^https?://!;
77              
78             return Net::Domain::TMCH::CRL->fromFile($r)
79             if !blessed $r;
80              
81             return $r
82             if $r->isa('Net::Domain::TMCH::CRL');
83              
84             return Net::Domain::TMCH::CRL->fromURI($r)
85             if $r->isa('URI');
86              
87             error __x"revocation list for THMC is not a {pkg}, filename, or uri"
88             , pkg => 'Net::Domain::TMCH::CRL';
89             }
90              
91             sub _smdrl($)
92             { my ($self, $r) = @_;
93              
94             return ()
95             unless defined $r;
96              
97             return map $self->_smdrl($_), @$r
98             if ref $r eq 'ARRAY';
99              
100             $r = URI->new($r)
101             if !blessed $r && $r =~ m!^https?://!;
102              
103             return Net::Domain::SMD::RL->fromFile($r)
104             if !blessed $r;
105              
106             return $r
107             if $r->isa('Net::Domain::SMD::RL');
108              
109             return Net::Domain::SMD::RL->fromURI($r)
110             if $r->isa('URI');
111            
112             error __x"revocation list for SMD is not a {pkg} or filename"
113             , pkg => 'Net::Domain::SMD::RL';
114             }
115              
116             #-------------------------
117              
118              
119             sub smdAdmin() {shift->{NDT_smds}}
120             sub isPilot() {shift->{NDT_pilot}}
121             sub tmchCertificate(){shift->{NDT_tmch_cert}}
122             sub tmchCA() {shift->{NDT_tmch_ca}}
123             sub certRevocations(){shift->{NDT_crl}}
124             sub smdRevocations() { @{shift->{NDT_smdrl}} }
125              
126             #-------------------------
127              
128              
129             sub smd($%)
130             { my ($self, $xml, %args) = @_;
131              
132             my ($smd, $source) = $self->smdAdmin->from($xml);
133             return $smd
134             if !$smd || $args{trust_certificates};
135              
136             my $tmch_cert = $self->tmchCertificate;
137              
138             my ($tmv_cert) = $smd->certificates(issuer => $tmch_cert->subject);
139             defined $tmv_cert
140             or error __x"smd in {source} does not contain a TMV certificate"
141             , source => $source;
142              
143             $self->tmchCA->verify($tmv_cert)
144             or error __x"invalid TMV certificate in {source}", source => $source;
145              
146             $args{accept_expired} || ! $tmv_cert->checkend(0)
147             or error __x"the TMV certificate in {source} has expired"
148             , source => $source;
149              
150             $self->certRevocations->isRevoked($tmv_cert)
151             and error __x"smd in {source} contains revoked TMV certificate"
152             , source => $source;
153              
154             foreach my $rl ($self->smdRevocations)
155             { error __x"smd in {source} is revoked according to {list}"
156             , source => $source, list => $rl->source
157             if $rl->isRevoked($smd);
158             }
159              
160             $smd;
161             }
162              
163              
164             sub createSignedMark($%)
165             { my ($self, $doc, $data, %args) = @_;
166             $self->smdAdmin->createSignedMark($doc, $data, \%args);
167             }
168              
169             1;