#! /usr/bin/perl

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

my $opt_template = "sign.cnf";
my $opt_type = "client";
my $opt_init;

sub genpw($);
sub init($);

MAIN: {
	GetOptions(
		"init" => \$opt_init,
		"t|type=s" => \$opt_type,
		"h|help" => sub { pod2usage(-exit => 0, -verbose => 1) },
		"m|man" => sub { pod2usage(-exit => 0, -verbose => 2, 
			-noperldoc => system("perldoc -V >/dev/null 2>&1")) }
	) and @ARGV or pod2usage;
	my $CN = shift;

	if ($opt_init) {
		init($CN);
		exit 0;
	}

	my $csr = "requests/$CN/csr.pem";
	if (not -f $csr) {
		die "Can't find the request in $csr: $!\n";
	}

	$ENV{OPENSSL_CONF} = "ca/openssl.cnf";
	system openssl => "ca",
		-in => $csr,
		-out => "requests/$CN/crt.pem.tmp",
		-extensions => $opt_type;

	if ($?) {
		unlink "requests/$CN/crt.pem.tmp";
		exit 2;
	}

	move "requests/$CN/crt.pem.tmp" => "requests/$CN/crt.pem";
	say "Certificate saved to requests/$CN/crt.pem";

}

sub init($) {
	my $cn = shift;

	mkdir "ca/newcerts";
	mkdir "ca/private";
	open(my $x, ">>ca/index.txt");
	close($x);

	return if -f "ca/ca-crt.pem";

	if (not -f "ca/ca-csr.pem") {
		system "bin/request", "--init";
		system "bin/request", "--check" => $cn;
		$? and system "bin/request", "--template" => "ca-request.cnf", $cn;
		{
			local @ARGV = "requests/$cn/secret";
			chomp($_ = "REMEMBER(!) THE PASSPHRASE: " . <>);
			unlink("requests/$cn/secret") or die "@ARGV: $!";
			$_ = join "\n", "-" x length, $_, "-" x length;
			say;
		}
		copy "requests/$cn/csr.pem" => "ca/ca-csr.pem";
		move "requests/$cn/key.pem" => "ca/private/ca-key.pem";
	}


	$ENV{OPENSSL_CONF} = "ca/openssl.cnf";
	system(openssl => qw(
		ca -selfsign 
		   -create_serial -out ca/ca-crt.pem -days 3650
		   -extensions v3_ca
		   -in ca/ca-csr.pem));
}

__END__

=head1 NAME

  sign - sign a ssl certificate request

=head1 SYNOPSIS

  sign --init {CN}
  sign [--type=client|server] {CN}

=head1 DESCRIPTION

B<sign> signs a SSL certificate signing request. 
The signing request is expected in F<requests/>I<CN>F</csr.pem>.
The resulting certificate will be written to
F<requests>/I<CN>F</crt.pem>.

=head1 OPTIONS

=over

=item B<--type> client|server

Signs the certificate as client or server certificate (default: client)

=item B<--init>

Using the option a new CA will get initialized. It will create a CSR if 
there is no CSR in F<requests/>I<CN>/F<csr.pem> already. For security
reasons the KEY file found in F<requests/>I<CN>/F<key.pem> will be printed to
stdout and B<deleted>.

=cut

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