bin/ca
changeset 1 f44419b55cf0
parent 0 730be7994b86
child 2 72112c207284
equal deleted inserted replaced
0:730be7994b86 1:f44419b55cf0
     7 use File::Temp qw(tempdir);
     7 use File::Temp qw(tempdir);
     8 use File::Basename;
     8 use File::Basename;
     9 use Getopt::Long qw(GetOptionsFromArray);
     9 use Getopt::Long qw(GetOptionsFromArray);
    10 use Pod::Usage;
    10 use Pod::Usage;
    11 
    11 
    12 my $CA_CRT   = "CA/ca-crt.pem";
    12 my $CA_CRT = "CA/ca-crt.pem";
    13 my $CA_KEY   = "CA/private/ca-key.pem";
    13 my $CA_KEY = "CA/private/ca-key.pem";
    14 my $CA_DIR   = "./var";
    14 my $CA_DIR = "./var";
    15 
    15 
    16 my %TEMPLATE = (
    16 my %TEMPLATE = (
    17     ca => "templates/ca",
    17     ca  => "templates/ca",
    18     req => "templates/req",
    18     req => "templates/req",
    19 );
    19 );
    20 
    20 
    21 my $TMP      = tempdir("/tmp/$ENV{USER}.ca.XXXXXX", CLEANUP => 1);
    21 my $TMP = tempdir("/tmp/$ENV{USER}.ca.XXXXXX", CLEANUP => 1);
    22 
    22 
    23 my $opt_days    = undef;    # see the templates/ca for a default
    23 my $opt_days    = undef;    # see the templates/ca for a default
    24 my $opt_type    = undef;    # see the templates/ca for a default
    24 my $opt_type    = undef;    # see the templates/ca for a default
    25 my $opt_policy  = "de";     # see the templates/ca for a default
    25 my $opt_policy  = "de";     # see the templates/ca for a default
    26 my $opt_outfile = undef;
    26 my $opt_outfile = undef;
    27 my $opt_force = undef;
    27 my $opt_force   = undef;
    28 
    28 
    29 sub init_ca();
    29 sub init_ca();
    30 sub ask_pass($);
    30 sub ask_pass($);
    31 
    31 
    32 MAIN: {
    32 MAIN: {
    35     GetOptions(
    35     GetOptions(
    36         "d|days=i"    => \$opt_days,
    36         "d|days=i"    => \$opt_days,
    37         "t|type=s"    => \$opt_type,
    37         "t|type=s"    => \$opt_type,
    38         "p|policy=s"  => \$opt_policy,
    38         "p|policy=s"  => \$opt_policy,
    39         "o|outfile=s" => \$opt_outfile,
    39         "o|outfile=s" => \$opt_outfile,
    40 	"force"	      => \$opt_force,
    40         "force"       => \$opt_force,
    41 	"init"	      => sub { init_ca(); exit 0; },
    41         "init"        => sub { init_ca(); exit 0; },
    42         "h|help"      => sub { pod2usage(-verbose => 1, -exit => 0) },
    42         "h|help"      => sub { pod2usage(-verbose => 1, -exit => 0) },
    43         "m|man"       => sub { pod2usage(-verbose => 2, -exit => 0) },
    43         "m|man"       => sub { pod2usage(-verbose => 2, -exit => 0) },
    44     ) or pod2usage;
    44     ) or pod2usage;
    45 
    45 
    46     pod2usage if @ARGV > 1;
    46     pod2usage if @ARGV > 1;
    65         {
    65         {
    66             type   => $opt_type,
    66             type   => $opt_type,
    67             days   => $opt_days,
    67             days   => $opt_days,
    68             policy => "policy_$opt_policy",
    68             policy => "policy_$opt_policy",
    69             cacrt  => $CA_CRT,
    69             cacrt  => $CA_CRT,
    70 	    cakey  => $CA_KEY,
    70             cakey  => $CA_KEY,
    71 	    cadir  => $CA_DIR,
    71             cadir  => $CA_DIR,
    72         } => "$TMP/cnf"
    72         } => "$TMP/cnf"
    73     ) or die $tt2->error, "\n";
    73     ) or die $tt2->error, "\n";
    74 
    74 
    75     system( "openssl ca -config $TMP/cnf -in $TMP/csr -out $TMP/crt"
    75     system( "openssl ca -config $TMP/cnf -in $TMP/csr -out $TMP/crt"
    76           . " -utf8 \${CA_PASS:+-passin env:CA_PASS}");
    76           . " -utf8 \${CA_PASS:+-passin env:CA_PASS}");
   104 sub ask_pass($) {
   104 sub ask_pass($) {
   105     my $prompt = shift;
   105     my $prompt = shift;
   106     my @keys = ("x", "y");
   106     my @keys = ("x", "y");
   107 
   107 
   108     while (1) {
   108     while (1) {
   109 	print $prompt;
   109         print $prompt;
   110 	my $stty = `stty -g`;
   110         my $stty = `stty -g`;
   111 	system("stty -echo");
   111         system("stty -echo");
   112 	chomp($keys[0] = IO::File->new("/dev/tty")->getline());
   112         chomp($keys[0] = IO::File->new("/dev/tty")->getline());
   113 	print "\n";
   113         print "\n";
   114 	system("stty $stty");
   114         system("stty $stty");
   115 	print "please again for verification: ";
   115         print "please again for verification: ";
   116 	system("stty -echo");
   116         system("stty -echo");
   117 	chomp($keys[1] = IO::File->new("/dev/tty")->getline());
   117         chomp($keys[1] = IO::File->new("/dev/tty")->getline());
   118 	print "\n";
   118         print "\n";
   119 	system("stty $stty");
   119         system("stty $stty");
   120 	return $keys[0] if $keys[0] eq $keys[1];
   120         return $keys[0] if $keys[0] eq $keys[1];
   121 	print "keys mismatch, again\n";
   121         print "keys mismatch, again\n";
   122     }
   122     }
   123 }
   123 }
   124 
   124 
   125 sub init_ca() {
   125 sub init_ca() {
       
   126 
   126     # initialize the CA directory structure. This should
   127     # initialize the CA directory structure. This should
   127     # correspond to the values found in templates/ca
   128     # correspond to the values found in templates/ca
   128     die "$CA_DIR already exists" if -d $CA_DIR and not $opt_force;
   129     die "$CA_DIR already exists" if -d $CA_DIR and not $opt_force;
   129     mkpath(map { "$CA_DIR/$_" } qw(newcerts));
   130     mkpath(map { "$CA_DIR/$_" } qw(newcerts));
   130     mkpath(map { dirname $_ } $CA_CRT, $CA_KEY);
   131     mkpath(map { dirname $_ } $CA_CRT, $CA_KEY);
   131     (new IO::File ">$CA_DIR/index");
   132     (new IO::File ">$CA_DIR/index");
   132     (new IO::File ">$CA_DIR/serial")-> print("01\n");
   133     (new IO::File ">$CA_DIR/serial")->print("01\n");
   133 
   134 
   134     # now 
   135     # now
   135     my $tt2 = new Template or die $Template::ERROR;
   136     my $tt2 = new Template or die $Template::ERROR;
   136     $tt2->process($TEMPLATE{req},
   137     $tt2->process(
   137     {
   138         $TEMPLATE{req},
   138 	# not used yet
   139         {
   139     } => "$TMP/cnf") or die $tt2->error;
   140 
       
   141             # not used yet
       
   142         } => "$TMP/cnf"
       
   143     ) or die $tt2->error;
   140 
   144 
   141     $ENV{CA_PASS} = ask_pass("passphrase for CA key: ");
   145     $ENV{CA_PASS} = ask_pass("passphrase for CA key: ");
   142     system("openssl req -config $TMP/cnf -x509 -days 3650 -new -passout env:CA_PASS -keyout $TMP/ca-key.pem -out $TMP/ca-crt.pem")
   146     system(
   143     and exit;
   147 "openssl req -config $TMP/cnf -x509 -days 3650 -new -passout env:CA_PASS -keyout $TMP/ca-key.pem -out $TMP/ca-crt.pem"
       
   148     ) and exit;
   144 
   149 
   145     system("openssl x509 -in $TMP/ca-crt.pem -out $CA_CRT") and exit;
   150     system("openssl x509 -in $TMP/ca-crt.pem -out $CA_CRT") and exit;
   146     $_ = umask(077);
   151     $_ = umask(077);
   147     system("openssl rsa -in $TMP/ca-key.pem -des3 -passin env:CA_PASS -passout env:CA_PASS -out $CA_KEY") and exit;
   152     system(
       
   153 "openssl rsa -in $TMP/ca-key.pem -des3 -passin env:CA_PASS -passout env:CA_PASS -out $CA_KEY"
       
   154     ) and exit;
   148     umask($_);
   155     umask($_);
   149 
       
   150 
   156 
   151 }
   157 }
   152 
   158 
   153 __END__
   159 __END__
   154 
   160