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.02';
3             # ABSTRACT: Validate DNS Certification Authority Authorization (CAA) values
4              
5 3     3   2228 use 5.010;
  3         12  
6 3     3   16 use strict;
  3         7  
  3         53  
7 3     3   15 use warnings;
  3         5  
  3         87  
8              
9 3     3   14 use base 'Exporter';
  3         5  
  3         257  
10              
11 3     3   1146 use Syntax::Keyword::Junction qw(any);
  3         24336  
  3         18  
12 3     3   1456 use Data::Validate::URI qw(is_web_uri);
  3         113919  
  3         165  
13 3     3   1128 use Data::Validate::Email qw(is_email);
  3         60713  
  3         156  
14 3     3   738 use Taint::Util qw(untaint);
  3         771  
  3         20  
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 1204 my $class = shift;
26 2   33     17 return bless { @_ }, ref $class || $class;
27             }
28              
29              
30             sub is_caa_tag {
31 10     10 1 3502 my ($self, $value, %opts) = _maybe_oo(@_);
32              
33 10 100       33 unless (defined $opts{strict}) {
34 9         20 $opts{strict} = 1;
35             }
36              
37 10 100       26 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         281 untaint($value);
41              
42 7         26 return $value;
43             }
44             }
45             else {
46             # just a syntax check
47 1 50       4 unless ($value =~ /[^a-zA-Z0-9]/) {
48 1         3 untaint($value);
49              
50 1         5 return $value;
51             }
52             }
53              
54 2         42 return;
55             }
56              
57              
58             sub is_caa_value {
59 8     8 1 605 my ($self, $tag, $value) = _maybe_oo(@_);
60              
61 8         17 $tag = lc $tag;
62              
63 8 100       27 if ($tag eq 'issue') {
    50          
    50          
64 6         15 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         9 return;
74             }
75              
76              
77             sub is_caa_issue {
78 24     24 1 1084 my ($self, $value) = _maybe_oo(@_);
79              
80             # match using grammar from RFC 6844
81 24         78 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       446 if ($value =~ qr/^$issue_re$/) {
93 19         57 untaint($value);
94              
95 19         96 return $value;
96             }
97              
98 5         27 return;
99             }
100              
101              
102             sub is_caa_issuewild {
103 9     9 1 1436 return is_caa_issue(@_);
104             }
105              
106              
107             sub is_caa_iodef {
108 7     7 1 1057 my ($self, $value) = _maybe_oo(@_);
109              
110             # handle http/https uris
111 7 100       116 if (is_web_uri($value)) {
112 1         308 untaint($value);
113              
114 1         4 return $value;
115             }
116              
117 6 100       5974 if (lc $value =~ /^mailto:\S+@\S+/) {
118 3         12 $value =~ s/^mailto://;
119              
120 3 50       16 if (is_email($value)) {
121 3         2486 untaint($value);
122              
123 3         14 return $value;
124             }
125             }
126              
127 3         14 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__