#! /usr/bin/perl

use 5.010;
use strict;
use warnings;
use Getopt::Long;
use Template;
use Pod::Usage;

my $DIR = "requests";

my $opt_template = "request.cnf";
my $opt_check;
my $opt_init;

sub genpw($);

MAIN: {
	GetOptions(
		"template=s" => \$opt_template,
		"init" => \$opt_init,
		"check" => \$opt_check,
		"h|help" => sub { pod2usage(-exit => 0, -verbose => 1) },
		"m|man" => sub { pod2usage(-verbose => 2, -exit => 0,
			-noperldoc => system("perldoc -V 1>/dev/null 2>&1")) }
	) or pod2usage;

	my $CN = shift;
	mkdir($DIR), exit if $opt_init;

	pod2usage if not defined $CN;

	exit(-f "$DIR/$CN/csr.pem" ? 0 : 1)
		if $opt_check;

	rmdir($_ = "$DIR/$CN");	# succeeds if empty
	mkdir($_ = "$DIR/$CN") or die "directory $_: $!\n";

	# create the config template
	my $tt = Template->new(
		INCLUDE_PATH => "ca/templates",
	) or die "$Template::ERROR\n";
	$tt->process($opt_template, { CN => $CN }, "$DIR/$CN/openssl.cnf")
		or die $tt->error, "\n";
	$ENV{OPENSSL_CONF} = "$DIR/$CN/openssl.cnf";

	# create the password file
	open(my $pw, ">", $_ = "$DIR/$CN/secret") or die "$_: $!\n";
	say $pw genpw(10);
	close($pw);

	system(openssl => "req",
		qw(-new),
		-keyout => "$DIR/$CN/key.pem",
		-out => "$DIR/$CN/csr.pem",
		-passout => "file:$DIR/$CN/secret");
}

sub genpw($) {
	my $n = shift;
	my @chars = (qw(_ . - /), "a".."z", "A".."Z", 0..9);
	join "" => map { @chars[rand @chars + 1] } (1..$n);
}


__END__

=head1 NAME

  request - generate a ssl certificate request

=head1 SYNOPSIS

  request [--init]
  request [--template={file}] {CN}

=head1 DESCRIPTION

B<request> generates a new SSL certificate signing request. The files
(CSR and KEY) are placed in F<requests>. The generated key is protected
by a passphrase. The passphrase is written to stdout and has to be saved
by the caller!

=head1 OPTIONS

=over

=item B<--template> I<file>

The template file to be used for creating the request. The templates will be searched
unter F<ca/templates>. The only substituted item is [%CN%].  (default: request.cnf)

=back

=cut

# vim:sts=4 ts=4 sw=4 aw ai sm:
