File Coverage

blib/lib/Net/ACME/Challenge/Pending/http_01/Handler.pm
Criterion Covered Total %
statement 52 57 91.2
branch 3 6 50.0
condition 2 6 33.3
subroutine 10 12 83.3
pod 0 3 0.0
total 67 84 79.7


line stmt bran cond sub pod time code
1             package Net::ACME::Challenge::Pending::http_01::Handler;
2              
3             =encoding utf-8
4              
5             =head1 NAME
6              
7             Net::ACME::Challenge::Pending::http_01::Handler - http-01 challenge handler
8              
9             =head1 DESCRIPTION
10              
11             This module handles the creation and removal of a domain control file for
12             http-01 challenges. Creation happens on instantiation; removal happens
13             when the object is destroyed.
14              
15             See C’s documentation for more
16             information, including a usage example.
17              
18             To handle challenges that have been unhandled (successfully or not),
19             see C.
20              
21             =cut
22              
23 5     5   15 use strict;
  5         4  
  5         101  
24 5     5   14 use warnings;
  5         26  
  5         91  
25              
26 5     5   458 use autodie;
  5         9736  
  5         42  
27              
28 5     5   17761 use Errno ();
  5         6  
  5         57  
29 5     5   15 use File::Spec ();
  5         42  
  5         53  
30              
31 5     5   1039 use Net::ACME::Constants ();
  5         6  
  5         2097  
32              
33             #docroot, token, key_authz
34             sub new {
35 3     3 0 15 my ( $class, %opts ) = @_;
36              
37 3         10 my $docroot_relative_path = "$Net::ACME::Constants::HTTP_01_CHALLENGE_DCV_DIR_IN_DOCROOT/$opts{'token'}";
38              
39 3         9 my $file_path = "$opts{'docroot'}/$docroot_relative_path";
40              
41 3         14 _mkdir_if_not_exists("$opts{'docroot'}/$Net::ACME::Constants::HTTP_01_CHALLENGE_DCV_DIR_IN_DOCROOT");
42              
43 3         19 local ( $!, $^E );
44              
45 3         11 open my $wfh, '>', $file_path;
46 3         3872 chmod 0644, $file_path;
47 3         632 syswrite $wfh, $opts{'key_authz'};
48 3         2853 close $wfh;
49              
50             my $self = {
51             _euid => $>,
52             _path => $file_path,
53             _docroot_relative_path => $docroot_relative_path,
54 3         1789 _content => $opts{'key_authz'},
55             };
56              
57 3         28 return bless $self, $class;
58             }
59              
60             sub expected_content {
61 0     0 0 0 my ($self) = @_;
62              
63 0         0 return $self->{'_content'};
64             }
65              
66             sub verification_path {
67 0     0 0 0 my ($self) = @_;
68              
69 0         0 return "/$self->{'_docroot_relative_path'}";
70             }
71              
72             sub DESTROY {
73 3     3   2199 my ($self) = @_;
74              
75 3 50       49 if ( $> != $self->{'_euid'} ) {
76 0         0 die "XXX attempt to delete “$self->{'_path'}” with EUID $>; created with EUID $self->{'_euid'}!";
77             }
78              
79 3         13 _unlink_if_exists( $self->{'_path'} );
80              
81 3         12 return;
82             }
83              
84             sub _mkdir_if_not_exists {
85 3     3   5 my ($path) = @_;
86              
87             #cf. eval_bug.readme
88 3         5 my $eval_err = $@;
89              
90 3         38 local ( $!, $^E );
91              
92 3         22 my @ppath = File::Spec->splitdir($path);
93 3         5 pop @ppath;
94 3         18 my $ppath_str = File::Spec->catdir(@ppath);
95              
96 3         8 for my $p ($ppath_str, $path) {
97 6         19 eval { mkdir $p };
  6         20  
98 6 50 33     5014 die if $@ && $@->errno() != Errno::EEXIST();
99             }
100              
101 3         9 $@ = $eval_err;
102              
103 3         14 return;
104             }
105              
106             sub _unlink_if_exists {
107 3     3   4 my ($path) = @_;
108              
109 3         4 local $@;
110 3         12 local ( $!, $^E );
111 3         5 eval { unlink $path };
  3         9  
112 3 50 33     872 die if $@ && $@->errno() != Errno::ENOENT();
113              
114 3         14 return;
115             }
116              
117             1;