1# $OpenBSD: Httpd.pm,v 1.3 2018/05/19 13:57:43 jsing Exp $ 2 3# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org> 4# Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18use strict; 19use warnings; 20 21package Httpd; 22use parent 'Proc'; 23use Carp; 24use File::Basename; 25 26sub new { 27 my $class = shift; 28 my %args = @_; 29 $args{chroot} ||= "."; 30 $args{docroot} ||= "htdocs"; 31 $args{logfile} ||= $args{chroot}."/httpd.log"; 32 $args{up} ||= $args{dryrun} || "server_launch: "; 33 $args{down} ||= $args{dryrun} ? "httpd.conf:" : "parent terminating"; 34 $args{func} = sub { Carp::confess "$class func may not be called" }; 35 $args{conffile} ||= "httpd.conf"; 36 my $self = Proc::new($class, %args); 37 ref($self->{http}) eq 'ARRAY' 38 or $self->{http} = [ split("\n", $self->{http} || "") ]; 39 $self->{listenaddr} 40 or croak "$class listen addr not given"; 41 $self->{listenport} 42 or croak "$class listen port not given"; 43 44 my $test = basename($self->{testfile} || ""); 45 # tls does not allow a too long session id, so truncate it 46 substr($test, 25, length($test) - 25, "") if length($test) > 25; 47 open(my $fh, '>', $self->{conffile}) 48 or die ref($self), " conf file $self->{conffile} create failed: $!"; 49 50 # substitute variables in config file 51 my $curdir = dirname($0) || "."; 52 my $connectport = $self->{connectport}; 53 my $connectaddr = $self->{connectaddr}; 54 my $listenaddr = $self->{listenaddr}; 55 my $listenport = $self->{listenport}; 56 57 print $fh "prefork 1\n"; # only crashes of first child are observed 58 print $fh "chroot \"".$args{docroot}."\"\n"; 59 print $fh "logdir \"".$args{chroot}."\"\n"; 60 61 my @http = @{$self->{http}}; 62 print $fh "server \"www.$test.local\" {"; 63 my $tls = $self->{listentls} ? "tls " : ""; 64 print $fh "\n\tlisten on $self->{listenaddr} ". 65 "${tls}port $self->{listenport}" unless grep { /^listen / } @http; 66 # substitute variables in config file 67 foreach (@http) { 68 s/(\$[a-z]+)/$1/eeg; 69 } 70 print $fh map { "\n\t$_" } @http; 71 if ($self->{listentls}) { 72 print $fh "\n"; 73 print $fh "\ttls certificate \"".$args{chroot}."/server.crt\"\n"; 74 print $fh "\ttls key \"".$args{chroot}."/server.key\""; 75 $self->{verifytls} 76 and print $fh "\n\ttls client ca \"".$args{chroot}."/ca.crt\""; 77 } 78 print $fh "\n\troot \"/\""; 79 print $fh "\n\tlog style combined"; 80 print $fh "\n}\n"; 81 82 return $self; 83} 84 85sub child { 86 my $self = shift; 87 my @sudo = $ENV{SUDO} ? $ENV{SUDO} : (); 88 my @ktrace = $ENV{KTRACE} ? ($ENV{KTRACE}, "-i") : (); 89 my $httpd = $ENV{HTTPD} ? $ENV{HTTPD} : "httpd"; 90 my @cmd = (@sudo, @ktrace, $httpd, "-dvv", "-f", $self->{conffile}); 91 print STDERR "execute: @cmd\n"; 92 exec @cmd; 93 die ref($self), " exec '@cmd' failed: $!"; 94} 95 961; 97