File Coverage

blib/lib/Data/Validate/DNS/CAA.pm
Criterion Covered Total %
statement 60 62 96.7
branch 20 24 83.3
condition 1 3 33.3
subroutine 15 15 100.0
pod 6 6 100.0
total 102 110 92.7


line stmt bran cond sub pod time code
1             package Data::Validate::DNS::CAA;
2             $Data::Validate::DNS::CAA::VERSION = '0.04';
3             # ABSTRACT: Validate DNS Certification Authority Authorization (CAA) values
4              
5 3     3   1883 use 5.010;
  3         11  
6 3     3   12 use strict;
  3         7  
  3         47  
7 3     3   12 use warnings;
  3         5  
  3         66  
8              
9 3     3   14 use base 'Exporter';
  3         4  
  3         176  
10              
11 3     3   1101 use Syntax::Keyword::Junction qw(any);
  3         24832  
  3         17  
12 3     3   1449 use Data::Validate::URI qw(is_web_uri);
  3         112480  
  3         150  
13 3     3   1136 use Data::Validate::Email qw(is_email);
  3         60675  
  3         152  
14 3     3   796 use Taint::Util qw(untaint);
  3         805  
  3         18  
15              
16             our @EXPORT_OK = qw(
17             is_caa_tag
18             is_caa_value
19             is_caa_issue
20             is_caa_iodef
21             is_caa_issuewild);
22              
23              
24             sub new {
25 2     2 1 1134 my $class = shift;
26 2   33     15 return bless { @_ }, ref $class || $class;
27             }
28              
29              
30             sub is_caa_tag {
31 10     10 1 3479 my ($self, $value, %opts) = _maybe_oo(@_);
32              
33 10 100       34 unless (defined $opts{strict}) {
34 9         19 $opts{strict} = 1;
35             }
36              
37 10 100       23 if ($opts{strict}) {
38             # strict mode, only allow registered tag names
39 9 100       33 if (lc $value eq any(qw(issue issuewild iodef))) {
40 7         271 untaint($value);
41              
42 7         27 return $value;
43             }
44             }
45             else {
46             # just a syntax check
47 1 50       5 unless ($value =~ /[^a-zA-Z0-9]/) {
48 1         3 untaint($value);
49              
50 1         4 return $value;
51             }
52             }
53              
54 2         43 return;
55             }
56              
57              
58             sub is_caa_value {
59 8     8 1 654 my ($self, $tag, $value) = _maybe_oo(@_);
60              
61 8         19 $tag = lc $tag;
62              
63 8 100       27 if ($tag eq 'issue') {
    50          
    50          
64 6         14 return is_caa_issue($value);
65             }
66             elsif ($tag eq 'issuewild') {
67 0         0 return is_caa_issue($value);
68             }
69             elsif ($tag eq 'iodef') {
70 0         0 return is_caa_iodef($value);
71             }
72              
73 2         7 return;
74             }
75              
76              
77             sub is_caa_issue {
78 24     24 1 1053 my ($self, $value) = _maybe_oo(@_);
79              
80             # match using grammar from RFC 6844
81 24         74 my $issue_re = qr{
82             (?&issueval)
83             (?(DEFINE)
84             (? \s* (?&domain)? \s* (?&tagstring)? )
85             (? (?&label) (?: . (?&label) )* )
86             (?
87             (? ; (?: \s* (?¶meter) )* \s* )
88             (? [0-9A-Za-z]+ = [\x21-\x7e]* )
89             )
90             }x;
91              
92 24 100       461 if ($value =~ qr/^$issue_re$/) {
93 19         63 untaint($value);
94              
95 19         96 return $value;
96             }
97              
98 5         24 return;
99             }
100              
101              
102             sub is_caa_issuewild {
103 9     9 1 1421 return is_caa_issue(@_);
104             }
105              
106              
107             sub is_caa_iodef {
108 7     7 1 1044 my ($self, $value) = _maybe_oo(@_);
109              
110             # handle http/https uris
111 7 100       111 if (is_web_uri($value)) {
112 1         306 untaint($value);
113              
114 1         4 return $value;
115             }
116              
117 6 100       4995 if (lc $value =~ /^mailto:\S+@\S+/) {
118 3         11 $value =~ s/^mailto://;
119              
120 3 50       20 if (is_email($value)) {
121 3         2439 untaint($value);
122              
123 3         13 return $value;
124             }
125             }
126              
127 3         11 return;
128             }
129              
130             sub _maybe_oo {
131 49 100   49   137 my $self = shift if ref $_[0];
132              
133 49         137 return ($self, @_);
134             }
135              
136             1;
137              
138             __END__