#!/usr/bin/perl -T #---------------------------------------------------------------------- # Let's Encrypt ACME client (minimal webserver for answering challenges) # Copyright © 2015 Guilhem Moulin # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #---------------------------------------------------------------------- use strict; use warnings; my $ROOT = '/.well-known/acme-challenge'; $_ = // exit; my $proto = s/ HTTP\/(1\.[01])\r\n\z// ? $1 : die "Error: Bad request\n"; my $method = s/\A(GET|HEAD) // ? $1 : die "Error: Bad request\n"; # Consume the headers (and ignore them) while (defined (my $h = )) { last if $h eq "\r\n" }; my ($status_line, $content_type, $content); if (/\A\Q$ROOT\E\/([A-Za-z0-9_\-]+)\z/ and -f $1) { if (open my $fh, '<', $1) { ($status_line, $content_type) = ('200 OK', 'application/jose+json'); $content = do { local $/ = undef; <$fh> }; close $fh; } else { $status_line = '403 Forbidden'; } } print "HTTP/$proto ", ($status_line // '404 Not Found'), "\r\n"; print "Content-Type: $content_type\r\n" if defined $content_type; print "Content-Length: ".length($content)."\r\n" if defined $content; print "Connection: close\r\n"; print "\r\n"; print $content if defined $content and $method eq 'GET';