File Coverage

blib/lib/HTTP/Daemon/SSL.pm
Criterion Covered Total %
statement 28 68 41.1
branch 1 36 2.7
condition 3 11 27.2
subroutine 10 14 71.4
pod 3 4 75.0
total 45 133 33.8


line stmt bran cond sub pod time code
1             #
2             # This package derived almost entirely from HTTP::Daemon,
3             # owned by Gisle Aas. Changes include minor alterations in
4             # the documentation to reflect the use of IO::Socket::SSL
5             # and modified new(),accept() functions that use IO::Socket::SSL
6              
7 2     2   56055 use strict;
  2         5  
  2         158  
8              
9             package HTTP::Daemon::SSL;
10              
11             =head1 NAME
12              
13             HTTP::Daemon::SSL - a simple http server class with SSL support
14              
15             =head1 SYNOPSIS
16              
17             use HTTP::Daemon::SSL;
18             use HTTP::Status;
19              
20             # Make sure you have a certs/ directory with "server-cert.pem"
21             # and "server-key.pem" in it before running this!
22             my $d = HTTP::Daemon::SSL->new || die;
23             print "Please contact me at: url, ">\n";
24             while (my $c = $d->accept) {
25             while (my $r = $c->get_request) {
26             if ($r->method eq 'GET' and $r->url->path eq "/xyzzy") {
27             # remember, this is *not* recommened practice :-)
28             $c->send_file_response("/etc/passwd");
29             } else {
30             $c->send_error(RC_FORBIDDEN)
31             }
32             }
33             $c->close;
34             undef($c);
35             }
36              
37             =head1 DESCRIPTION
38              
39             Instances of the I class are HTTP/1.1 servers that
40             listen on a socket for incoming requests. The I is a
41             sub-class of I, so you can perform socket operations
42             directly on it too.
43              
44             The accept() method will return when a connection from a client is
45             available. In a scalar context the returned value will be a reference
46             to a object of the I class which is another
47             I subclass. In a list context a two-element array
48             is returned containing the new I reference
49             and the peer address; the list will be empty upon failure. (Note that version
50             1.02 erroneously did not honour list context). Calling
51             the get_request() method on the I object
52             will read data from the client and return an I object
53             reference.
54              
55             This HTTPS daemon does not fork(2) for you. Your application, i.e. the
56             user of the I is reponsible for forking if that is
57             desirable. Also note that the user is responsible for generating
58             responses that conform to the HTTP/1.1 protocol. The
59             I class provides some methods that make this easier.
60              
61             =head1 METHODS
62              
63             The following methods are the only differences from the I base class:
64              
65             =over 4
66              
67             =cut
68              
69              
70 2     2   11 use vars qw($VERSION @ISA $PROTO $DEBUG);
  2         4  
  2         189  
71              
72 2     2   4013 use IO::Socket::SSL;
  2         346126  
  2         19  
73 2     2   2449 use HTTP::Daemon;
  2         121813  
  2         35  
74              
75             $VERSION = "1.05_01";
76             @ISA = qw(IO::Socket::SSL HTTP::Daemon);
77              
78             =item $d = new HTTP::Daemon::SSL
79              
80             The constructor takes the same parameters as the
81             I constructor. It can also be called without specifying
82             any parameters, but you will have to make sure that you have an SSL certificate
83             and key for the server in F and F.
84             See the IO::Socket::SSL documentation for how to change these default locations
85             and specify many other aspects of SSL behavior. The daemon will then set up a
86             listen queue of 5 connections and allocate some random port number. A server
87             that wants to bind to some specific address on the standard HTTPS port will be
88             constructed like this:
89              
90             $d = new HTTP::Daemon::SSL
91             LocalAddr => 'www.someplace.com',
92             LocalPort => 443;
93              
94             =cut
95              
96             sub new
97             {
98 1     1 1 1188 my ($class, %args) = @_;
99 1   50     6 $args{Listen} ||= 5;
100 1   50     9 $args{Proto} ||= 'tcp';
101 1   50     10 $args{SSL_error_trap} ||= \&ssl_error;
102 1         20 return $class->SUPER::new(%args);
103             }
104              
105             sub accept
106             {
107 0     0 1 0 my $self = shift;
108 0   0     0 my $pkg = shift || "HTTP::Daemon::ClientConn::SSL";
109 0         0 my ($sock, $peer) = IO::Socket::SSL::accept($self,$pkg);
110 0 0       0 if ($sock) {
111 0         0 ${*$sock}{'httpd_daemon'} = $self;
  0         0  
112 0 0       0 return wantarray ? ($sock, $peer) : $sock;
113             }
114             else {
115 0         0 return;
116             }
117             }
118              
119 1     1   63 sub _default_port { 443; }
120 1     1   8 sub _default_scheme { "https"; }
121              
122             sub url
123             {
124 1     1 1 3087 my $self = shift;
125 1         16 my $url = $self->SUPER::url;
126 1 50       25 return $url if ($self->can("HTTP::Daemon::_default_port"));
127            
128             # Workaround for old versions of HTTP::Daemon
129 0           $url =~ s!^http:!https:!;
130 0 0         $url =~ s!/$!:80/! unless ($url =~ m!:(?:\d+)/$!);
131 0           $url =~ s!:443/$!/!;
132 0           return $url;
133             }
134              
135              
136             package HTTP::Daemon::SSL::DummyDaemon;
137 2     2   2353 use vars qw(@ISA);
  2         37  
  2         469  
138             @ISA = qw(HTTP::Daemon);
139 0     0     sub new { bless [], shift; }
140              
141             package HTTP::Daemon::SSL;
142              
143             sub ssl_error {
144 0     0 0   my ($self, $error) = @_;
145 0           ${*$self}{'httpd_client_proto'} = 1000;
  0            
146 0           ${*$self}{'httpd_daemon'} = new HTTP::Daemon::SSL::DummyDaemon;
  0            
147 0 0 0       if ($error =~ /http/i and $self->opened) {
148 0           $self->send_error(400, "Your browser attempted to make an unencrypted\n ".
149             "request to this server, which is not allowed. Try using\n ".
150             "HTTPS instead.\n");
151             }
152 0           $self->kill_socket;
153             }
154              
155             # we're not overriding any methods here, but we are inserting IO::Socket::SSL
156             # into the message dispatch tree
157              
158             package HTTP::Daemon::ClientConn::SSL;
159 2     2   11 use vars qw(@ISA $DEBUG);
  2         3  
  2         707  
160             @ISA = qw(IO::Socket::SSL HTTP::Daemon::ClientConn);
161             *DEBUG = \$HTTP::Daemon::DEBUG;
162              
163             sub _need_more
164             {
165 0     0     my $self = shift;
166 0 0         if ($_[1]) {
167 0           my($timeout, $fdset) = @_[1,2];
168 0 0         print STDERR "select(,,,$timeout)\n" if $DEBUG;
169 0           my $n = select($fdset,undef,undef,$timeout);
170 0 0         unless ($n) {
171 0 0         $self->reason(defined($n) ? "Timeout" : "select: $!");
172 0           return;
173             }
174             }
175 0           my $total = 0;
176 0           while (1){
177 0 0         print STDERR sprintf("sysread() already %d\n",$total) if $DEBUG;
178 0           my $n = sysread($self, $_[0], 2048, length($_[0]));
179 0 0         print STDERR sprintf("sysread() just \$n=%s\n",(defined $n?$n:'undef')) if $DEBUG;
    0          
180 0 0         $total += $n if defined $n;
181 0 0         last if $! =~ 'Resource temporarily unavailable';
182             #SSL_Error because of aggressive reading
183            
184 0 0         $self->reason(defined($n) ? "Client closed" : "sysread: $!") unless $n;
    0          
185 0 0         last unless $n;
186 0 0         last unless $n == 2048;
187             }
188 0           $total;
189             }
190              
191              
192             =back
193              
194             =head1 BUGS
195              
196             There is a problem with the interaction between the L base class and
197             L buffering which causes large post or put actions (>66k or so,
198             depending on your OS) to hang.
199              
200             See L.
201              
202             =head1 SEE ALSO
203              
204             RFC 2068
205              
206             L, L, L
207              
208             Github repository: L
209              
210             =head1 COPYRIGHT
211              
212             Code and documentation from HTTP::Daemon Copyright 1996-2001, Gisle Aas
213             Changes Copyright 2003-2004, Peter Behroozi
214             Changes Copyright 2007-2009, Mark Aufflick C<< >>
215              
216             This library is free software; you can redistribute it and/or
217             modify it under the same terms as Perl itself.
218              
219             =cut
220              
221             1;