bin/ca
changeset 2 72112c207284
parent 1 f44419b55cf0
--- a/bin/ca	Tue Jan 26 23:43:31 2010 +0100
+++ b/bin/ca	Wed Jan 27 00:30:39 2010 +0100
@@ -8,14 +8,15 @@
 use File::Basename;
 use Getopt::Long qw(GetOptionsFromArray);
 use Pod::Usage;
+use feature qw(switch);
 
 my $CA_CRT = "CA/ca-crt.pem";
 my $CA_KEY = "CA/private/ca-key.pem";
 my $CA_DIR = "./var";
 
 my %TEMPLATE = (
-    ca  => "templates/ca",
-    req => "templates/req",
+    ca  => "lib/templates/ca",
+    req => "lib/templates/req",
 );
 
 my $TMP = tempdir("/tmp/$ENV{USER}.ca.XXXXXX", CLEANUP => 1);
@@ -37,8 +38,8 @@
         "t|type=s"    => \$opt_type,
         "p|policy=s"  => \$opt_policy,
         "o|outfile=s" => \$opt_outfile,
-        "force"       => \$opt_force,
-        "init"        => sub { init_ca(); exit 0; },
+        "f|force"     => \$opt_force,
+        "i|init"      => sub { eval { init_ca() }; if ($@) { warn $@; exit 1 }; exit 0 },
         "h|help"      => sub { pod2usage(-verbose => 1, -exit => 0) },
         "m|man"       => sub { pod2usage(-verbose => 2, -exit => 0) },
     ) or pod2usage;
@@ -46,13 +47,10 @@
     pod2usage if @ARGV > 1;
     $csrfile = $ARGV[0];    # don't shift, we'll need it later!
 
-    my $csr = new IO::File "$TMP/csr" => "w+"
-      or die "Can't open +>$TMP/csr: $!\n";
-    my $cnf = new IO::File "$TMP/cnf" => "w"
-      or die "Can't open >$TMP/cnf: $!\n";
-    my $crt = new IO::File "$TMP/crt" => "w+"
-      or die "Can't open +>$TMP/crt: $!\n";
-    my $tt2 = new Template or die $Template::ERROR;
+    my $cnf = new IO::File ">$TMP/cnf"  or die "Can't open >$TMP/cnf: $!\n";
+    my $csr = new IO::File "+>$TMP/csr" or die "Can't open +>$TMP/csr: $!\n";
+    my $crt = new IO::File "+>$TMP/crt" or die "Can't open +>$TMP/crt: $!\n";
+    my $tt2 = new Template              or die $Template::ERROR;
 
     # get a private copy of the request
     print { IO::File->new("|openssl req -out $TMP/csr") } <>;
@@ -86,21 +84,35 @@
     }
 
     # to be sure not to have an invalid/dangerous file name
-    fork() or do {
-        open(STDOUT, ">$outfile")
-          if defined $outfile
+    if (fork() == 0) {
+	if (defined $outfile) {
+	    open(STDOUT, ">$outfile")
               or die "Can't open >$outfile: $!\n";
+	    }
         exec "openssl x509 -in $TMP/crt";
         die "Can't exec openssl x509: $!\n";
-    };
-    wait;
+    }
+    else { wait }
+
+    # and now, since it's finally done, we'll copy the request
+    # away (for later use (thing about re-issuing a certificate))
+    my $subject = `openssl x509 -in $TMP/crt -noout -subject`;
+    if (my ($cn) = $subject =~ /CN=(\S+?)[,\/\s\$]/) {
+        if (fork() == 0) {
+            open(STDOUT, ">$CA_DIR/requests/$cn-csr.pem")
+              or die "Can't open >$CA_DIR/requests/$cn-csr.pem: $!\n";
+            exec "openssl req -in $TMP/csr";
+            die "Can't exec openssl req: $!\n";
+        }
+        else { wait }
+    }
+    else {
+        die "Can't determine the CN from $subject, not saving the request\n";
+    }
+
     exit;
 }
 
-sub verbose($) {
-    warn $_[0], " \n ";
-}
-
 sub ask_pass($) {
     my $prompt = shift;
     my @keys = ("x", "y");
@@ -127,7 +139,7 @@
     # initialize the CA directory structure. This should
     # correspond to the values found in templates/ca
     die "$CA_DIR already exists" if -d $CA_DIR and not $opt_force;
-    mkpath(map { "$CA_DIR/$_" } qw(newcerts));
+    mkpath(map { "$CA_DIR/$_" } qw(newcerts requests));
     mkpath(map { dirname $_ } $CA_CRT, $CA_KEY);
     (new IO::File ">$CA_DIR/index");
     (new IO::File ">$CA_DIR/serial")->print("01\n");
@@ -154,6 +166,8 @@
     ) and exit;
     umask($_);
 
+    return 0;
+
 }
 
 __END__