#!/usr/bin/perl -w
# you need to have configured your systems openssl.cnf (usually /etc/ssl/openssl.cnf)
# and have an existing CA cert/key pair.
# TODO more error checking - should really check the exit status of the openssl commands
# and be smart about proceeding based on that data. They do bail on errors so it's safe
# to assume the user will know about it
# (c) huw@munted.org 2007
use strict;
use Getopt::Long;

my %opts;
GetOptions(\%opts, 'pem','pass', 'hostname=s', 'help', 'days=i', 'pkcs12');
&usage if (scalar keys %opts == 0 || $opts{help});
die "Required parameter '-h hostname' missing\n" if !$opts{hostname};

my $days = $opts{days} || 7300;
my $openssl = "/usr/bin/openssl";
my $crtdir = "/usr/share/ssl/$opts{hostname}";
my $cadir = "/usr/share/ssl/CA/";
my $cakey = "$cadir/private/cakey.pem";
my $cacrt = "$cadir/cacert.pem";
my $key = "$crtdir/$opts{hostname}.key";
my $crt = "$crtdir/$opts{hostname}.crt";
my $csr = "$crtdir/$opts{hostname}.csr";
my $pem = "$crtdir/$opts{hostname}";
my $p12 = "$crtdir/$opts{hostname}.p12";

mkdir $crtdir if (! -d $crtdir);

if (!$opts{pem}) {
	# gen the key
	system("$openssl genrsa -des3 -out $key 1024");
	# then the csr
	system("$openssl req -new -key $key -out $csr");
	# sign the csr
	system("$openssl x509 -req -days $days -in $csr -CA $cacrt -CAkey $cakey -out $crt");
	# remove the key pass
	&rm_pass if $opts{pass};
	# clean up
	unlink $csr;
	system("$openssl pkcs12 -export -clcerts -in $crt -inkey $key -out $p12") if $opts{pkcs12};
}
else {
    # request a new pem
    system("$openssl req -new -keyout $key -out $pem-new.req");
    # combine the csr and the key
    system("cat $key $pem-new.req > $pem.temp");
    # sign the pem
    print "Creating $pem.pem\n";
    system("$openssl ca -policy policy_anything -out $pem.pem -infiles $pem.temp");
    # remove the key pass
    &rm_key_pass("$key") if $opts{pass};
    # clean up
    unlink "$pem-new.req", "$pem.temp";
    system("$openssl pkcs12 -export -clcerts -in $pem.pem -inkey $key -out $p12") if $opts{pkcs12};
}   

sub rm_key_pass {
	my $key = shift;
	print "Removing key password\n";
	system("$openssl rsa -in $key -out $key.tmp");
	system("/bin/mv $key.tmp $key");
}

sub usage {
	print "Usage: $0 -help\n";
	print "or\n";
	print "Usage: $0 -hostname the.host.name [-days days -pass -pem]\n";
	print "Option\t\t\tValue\n";
	print "-hostname\t\tthe dns hostname this cert will be used with\n";
	print "-days\t\t\tdays cert is valid for (defaults to 7300 if unspecified)\n";
	print "-pass\t\t\ta bool flag that will create a passwordless key (e.g for apache)\n";
	print "-pem\t\t\ta bool flag that creates a pem cert\n";
	print "-pkcs12\t\t\ta bool flag that creates an additional pkcs12 cert\n";
	print "\t\t\tto use .p12s with java you _must_ set a password\n";
	exit 1;
}
