Code style: space after 'if'
[openssl.git] / apps / CA.pl.in
1 #!/usr/local/bin/perl
2 #
3 # CA - wrapper around ca to make it easier to use
4 #
5 # CA -newca ... will setup the right stuff
6 # CA -newreq[-nodes] ... will generate a certificate request 
7 # CA -sign ... will sign the generated request and output 
8
9 # default openssl.cnf file has setup as per the following
10 # demoCA ... where everything is stored
11
12 my $openssl;
13 if(defined $ENV{OPENSSL}) {
14         $openssl = $ENV{OPENSSL};
15 } else {
16         $openssl = "openssl";
17         $ENV{OPENSSL} = $openssl;
18 }
19
20 $SSLEAY_CONFIG=$ENV{"SSLEAY_CONFIG"};
21 $DAYS="-days 365";      # 1 year
22 $CADAYS="-days 1095";   # 3 years
23 $REQ="$openssl req $SSLEAY_CONFIG";
24 $CA="$openssl ca $SSLEAY_CONFIG";
25 $VERIFY="$openssl verify";
26 $X509="$openssl x509";
27 $PKCS12="$openssl pkcs12";
28
29 $CATOP="./demoCA";
30 $CAKEY="cakey.pem";
31 $CAREQ="careq.pem";
32 $CACERT="cacert.pem";
33 $CACRL="crl.pem";
34
35 $DIRMODE = 0777;
36
37 $RET = 0;
38
39 foreach (@ARGV) {
40         if ( /^(-\?|-h|-help)$/ ) {
41             print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify\n";
42             print STDERR "       CA -crl|-revoke cert-filename [reason]\n";
43             exit 0;
44         } elsif (/^-newcert$/) {
45             # create a certificate
46             system ("$REQ -new -x509 -keyout newkey.pem -out newcert.pem $DAYS");
47             $RET=$?;
48             print "Certificate is in newcert.pem, private key is in newkey.pem\n"
49         } elsif (/^-newreq$/) {
50             # create a certificate request
51             system ("$REQ -new -keyout newkey.pem -out newreq.pem $DAYS");
52             $RET=$?;
53             print "Request is in newreq.pem, private key is in newkey.pem\n";
54         } elsif (/^-newreq-nodes$/) {
55             # create a certificate request
56             system ("$REQ -new -nodes -keyout newkey.pem -out newreq.pem $DAYS");
57             $RET=$?;
58             print "Request is in newreq.pem, private key is in newkey.pem\n";
59         } elsif (/^-newca$/) {
60                 # if explicitly asked for or it doesn't exist then setup the
61                 # directory structure that Eric likes to manage things 
62             $NEW="1";
63             if ( "$NEW" || ! -f "${CATOP}/serial" ) {
64                 # create the directory hierarchy
65                 mkdir $CATOP, $DIRMODE;
66                 mkdir "${CATOP}/certs", $DIRMODE;
67                 mkdir "${CATOP}/crl", $DIRMODE ;
68                 mkdir "${CATOP}/newcerts", $DIRMODE;
69                 mkdir "${CATOP}/private", $DIRMODE;
70                 open OUT, ">${CATOP}/index.txt";
71                 close OUT;
72                 open OUT, ">${CATOP}/crlnumber";
73                 print OUT "01\n";
74                 close OUT;
75             }
76             if ( ! -f "${CATOP}/private/$CAKEY" ) {
77                 print "CA certificate filename (or enter to create)\n";
78                 $FILE = <STDIN>;
79
80                 chop $FILE;
81
82                 # ask user for existing CA certificate
83                 if ($FILE) {
84                     cp_pem($FILE,"${CATOP}/private/$CAKEY", "PRIVATE");
85                     cp_pem($FILE,"${CATOP}/$CACERT", "CERTIFICATE");
86                     $RET=$?;
87                 } else {
88                     print "Making CA certificate ...\n";
89                     system ("$REQ -new -keyout " .
90                         "${CATOP}/private/$CAKEY -out ${CATOP}/$CAREQ");
91                     system ("$CA -create_serial " .
92                         "-out ${CATOP}/$CACERT $CADAYS -batch " . 
93                         "-keyfile ${CATOP}/private/$CAKEY -selfsign " .
94                         "-extensions v3_ca " .
95                         "-infiles ${CATOP}/$CAREQ ");
96                     $RET=$?;
97                 }
98             }
99         } elsif (/^-pkcs12$/) {
100             my $cname = $ARGV[1];
101             $cname = "My Certificate" unless defined $cname;
102             system ("$PKCS12 -in newcert.pem -inkey newkey.pem " .
103                         "-certfile ${CATOP}/$CACERT -out newcert.p12 " .
104                         "-export -name \"$cname\"");
105             $RET=$?;
106             print "PKCS #12 file is in newcert.p12\n";
107             exit $RET;
108         } elsif (/^-xsign$/) {
109             system ("$CA -policy policy_anything -infiles newreq.pem");
110             $RET=$?;
111         } elsif (/^(-sign|-signreq)$/) {
112             system ("$CA -policy policy_anything -out newcert.pem " .
113                                                         "-infiles newreq.pem");
114             $RET=$?;
115             print "Signed certificate is in newcert.pem\n";
116         } elsif (/^(-signCA)$/) {
117             system ("$CA -policy policy_anything -out newcert.pem " .
118                                         "-extensions v3_ca -infiles newreq.pem");
119             $RET=$?;
120             print "Signed CA certificate is in newcert.pem\n";
121         } elsif (/^-signcert$/) {
122             system ("$X509 -x509toreq -in newreq.pem -signkey newreq.pem " .
123                                                                 "-out tmp.pem");
124             system ("$CA -policy policy_anything -out newcert.pem " .
125                                                         "-infiles tmp.pem");
126             $RET = $?;
127             print "Signed certificate is in newcert.pem\n";
128         } elsif (/^-verify$/) {
129             if (shift) {
130                 foreach $j (@ARGV) {
131                     system ("$VERIFY -CAfile $CATOP/$CACERT $j");
132                     $RET=$? if ($? != 0);
133                 }
134                 exit $RET;
135             } else {
136                     system ("$VERIFY -CAfile $CATOP/$CACERT newcert.pem");
137                     $RET=$?;
138                     exit $RET;
139             }
140         } elsif (/^-crl$/) {
141                 system ("$CA -gencrl -out $CATOP/crl/$CACRL");
142                 $RET=$?;
143                 print "Generated CRL is in $CATOP/crl/$CACRL\n" if (!$RET);
144         } elsif (/^-revoke$/) {
145                 my $cname = $ARGV[1];
146                 if (!defined $cname) {
147                         print "Certificate filename is required; reason optional.\n";
148                         exit 1;
149                 }
150                 my $reason = $ARGV[2];
151                 $reason = " -crl_reason $reason"
152                         if defined $reason && crl_reason_ok($reason);
153                 my $cmd = "$CA -revoke \"$cname\"".$reason;
154                 system ($cmd);
155                 $RET=$?;
156                 exit $RET;
157         } else {
158             print STDERR "Unknown arg $_\n";
159             print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify\n";
160             print STDERR "       CA -crl|-revoke cert-filename [reason]\n";
161             exit 1;
162         }
163 }
164
165 exit $RET;
166
167 sub crl_reason_ok {
168         my ($r) = shift;
169         if ($r eq 'unspecified' || $r eq 'keyCompromise' ||
170         $r eq 'CACompromise' || $r eq 'affiliationChanged' ||
171         $r eq 'superseded' || $r eq 'cessationOfOperation' ||
172         $r eq 'certificateHold' || $r eq 'removeFromCRL') {
173                 return 1;
174         }
175         print STDERR "Invalid CRL reason; must be one of:\n";
176         print STDERR "    unspecified, keyCompromise, CACompromise,\n";
177         print STDERR "    affiliationChanged, superseded, cessationOfOperation\n";
178         print STDERR "    certificateHold, removeFromCRL";
179         exit 1;
180 }
181
182 sub cp_pem {
183 my ($infile, $outfile, $bound) = @_;
184 open IN, $infile;
185 open OUT, ">$outfile";
186 my $flag = 0;
187 while (<IN>) {
188         $flag = 1 if (/^-----BEGIN.*$bound/) ;
189         print OUT $_ if ($flag);
190         if (/^-----END.*$bound/) {
191                 close IN;
192                 close OUT;
193                 return;
194         }
195 }
196 }
197