]>
Commit | Line | Data |
---|---|---|
291e94df | 1 | #!{- $config{perl} -} |
e0a65194 RS |
2 | # Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
3 | # | |
4 | # Licensed under the OpenSSL license (the "License"). You may not use | |
5 | # this file except in compliance with the License. You can obtain a copy | |
6 | # in the file LICENSE in the source distribution or at | |
7 | # https://www.openssl.org/source/license.html | |
8 | ||
8f3e97ba | 9 | # |
5a3aa852 | 10 | # Wrapper around the ca to make it easier to use |
9ab6fc59 RL |
11 | # |
12 | # {- join("\n# ", @autowarntext) -} | |
8f3e97ba | 13 | |
5a3aa852 RS |
14 | use strict; |
15 | use warnings; | |
16 | ||
17 | my $openssl = "openssl"; | |
18 | if(defined $ENV{'OPENSSL'}) { | |
19 | $openssl = $ENV{'OPENSSL'}; | |
62d27939 | 20 | } else { |
5a3aa852 | 21 | $ENV{'OPENSSL'} = $openssl; |
62d27939 AP |
22 | } |
23 | ||
5a3aa852 | 24 | my $verbose = 1; |
8f3e97ba | 25 | |
b0700d2c | 26 | my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"}; |
5a3aa852 RS |
27 | my $DAYS = "-days 365"; |
28 | my $CADAYS = "-days 1095"; # 3 years | |
b0700d2c RS |
29 | my $REQ = "$openssl req $OPENSSL_CONFIG"; |
30 | my $CA = "$openssl ca $OPENSSL_CONFIG"; | |
5a3aa852 RS |
31 | my $VERIFY = "$openssl verify"; |
32 | my $X509 = "$openssl x509"; | |
33 | my $PKCS12 = "$openssl pkcs12"; | |
8f3e97ba | 34 | |
5a3aa852 RS |
35 | # default openssl.cnf file has setup as per the following |
36 | my $CATOP = "./demoCA"; | |
37 | my $CAKEY = "cakey.pem"; | |
38 | my $CAREQ = "careq.pem"; | |
39 | my $CACERT = "cacert.pem"; | |
40 | my $CACRL = "crl.pem"; | |
41 | my $DIRMODE = 0777; | |
8f3e97ba | 42 | |
5a3aa852 RS |
43 | my $NEWKEY = "newkey.pem"; |
44 | my $NEWREQ = "newreq.pem"; | |
45 | my $NEWCERT = "newcert.pem"; | |
46 | my $NEWP12 = "newcert.p12"; | |
47 | my $RET = 0; | |
48 | my $WHAT = shift @ARGV; | |
49 | my $FILE; | |
8f3e97ba | 50 | |
5a3aa852 RS |
51 | # See if reason for a CRL entry is valid; exit if not. |
52 | sub crl_reason_ok | |
53 | { | |
54 | my $r = shift; | |
8f3e97ba | 55 | |
5a3aa852 RS |
56 | if ($r eq 'unspecified' || $r eq 'keyCompromise' |
57 | || $r eq 'CACompromise' || $r eq 'affiliationChanged' | |
58 | || $r eq 'superseded' || $r eq 'cessationOfOperation' | |
59 | || $r eq 'certificateHold' || $r eq 'removeFromCRL') { | |
60 | return 1; | |
61 | } | |
62 | print STDERR "Invalid CRL reason; must be one of:\n"; | |
63 | print STDERR " unspecified, keyCompromise, CACompromise,\n"; | |
64 | print STDERR " affiliationChanged, superseded, cessationOfOperation\n"; | |
65 | print STDERR " certificateHold, removeFromCRL"; | |
66 | exit 1; | |
8f3e97ba | 67 | } |
68 | ||
5a3aa852 RS |
69 | # Copy a PEM-format file; return like exit status (zero means ok) |
70 | sub copy_pemfile | |
71 | { | |
72 | my ($infile, $outfile, $bound) = @_; | |
73 | my $found = 0; | |
8f3e97ba | 74 | |
5a3aa852 RS |
75 | open IN, $infile || die "Cannot open $infile, $!"; |
76 | open OUT, ">$outfile" || die "Cannot write to $outfile, $!"; | |
77 | while (<IN>) { | |
78 | $found = 1 if /^-----BEGIN.*$bound/; | |
79 | print OUT $_ if $found; | |
80 | $found = 2, last if /^-----END.*$bound/; | |
81 | } | |
82 | close IN; | |
83 | close OUT; | |
84 | return $found == 2 ? 0 : 1; | |
98ecf60b D |
85 | } |
86 | ||
5a3aa852 RS |
87 | # Wrapper around system; useful for debugging. Returns just the exit status |
88 | sub run | |
89 | { | |
90 | my $cmd = shift; | |
91 | print "====\n$cmd\n" if $verbose; | |
92 | my $status = system($cmd); | |
93 | print "==> $status\n====\n" if $verbose; | |
94 | return $status >> 8; | |
8f3e97ba | 95 | } |
5a3aa852 RS |
96 | |
97 | ||
98 | if ( $WHAT =~ /^(-\?|-h|-help)$/ ) { | |
c1176ebf | 99 | print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-signcert|-verify\n"; |
5a3aa852 RS |
100 | print STDERR " CA -pkcs12 [certname]\n"; |
101 | print STDERR " CA -crl|-revoke cert-filename [reason]\n"; | |
102 | exit 0; | |
103 | } | |
104 | if ($WHAT eq '-newcert' ) { | |
105 | # create a certificate | |
106 | $RET = run("$REQ -new -x509 -keyout $NEWKEY -out $NEWCERT $DAYS"); | |
107 | print "Cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0; | |
108 | } elsif ($WHAT eq '-newreq' ) { | |
109 | # create a certificate request | |
110 | $RET = run("$REQ -new -keyout $NEWKEY -out $NEWREQ $DAYS"); | |
111 | print "Request is in $NEWREQ, private key is in $NEWKEY\n" if $RET == 0; | |
112 | } elsif ($WHAT eq '-newreq-nodes' ) { | |
113 | # create a certificate request | |
114 | $RET = run("$REQ -new -nodes -keyout $NEWKEY -out $NEWREQ $DAYS"); | |
115 | print "Request is in $NEWREQ, private key is in $NEWKEY\n" if $RET == 0; | |
116 | } elsif ($WHAT eq '-newca' ) { | |
117 | # create the directory hierarchy | |
118 | mkdir ${CATOP}, $DIRMODE; | |
119 | mkdir "${CATOP}/certs", $DIRMODE; | |
120 | mkdir "${CATOP}/crl", $DIRMODE ; | |
121 | mkdir "${CATOP}/newcerts", $DIRMODE; | |
122 | mkdir "${CATOP}/private", $DIRMODE; | |
123 | open OUT, ">${CATOP}/index.txt"; | |
124 | close OUT; | |
125 | open OUT, ">${CATOP}/crlnumber"; | |
126 | print OUT "01\n"; | |
127 | close OUT; | |
128 | # ask user for existing CA certificate | |
129 | print "CA certificate filename (or enter to create)\n"; | |
ce3d25d3 VD |
130 | $FILE = "" unless defined($FILE = <STDIN>); |
131 | $FILE =~ s{\R$}{}; | |
132 | if ($FILE ne "") { | |
5a3aa852 RS |
133 | copy_pemfile($FILE,"${CATOP}/private/$CAKEY", "PRIVATE"); |
134 | copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); | |
135 | } else { | |
136 | print "Making CA certificate ...\n"; | |
137 | $RET = run("$REQ -new -keyout" | |
138 | . " ${CATOP}/private/$CAKEY" | |
139 | . " -out ${CATOP}/$CAREQ"); | |
140 | $RET = run("$CA -create_serial" | |
141 | . " -out ${CATOP}/$CACERT $CADAYS -batch" | |
142 | . " -keyfile ${CATOP}/private/$CAKEY -selfsign" | |
143 | . " -extensions v3_ca" | |
144 | . " -infiles ${CATOP}/$CAREQ") if $RET == 0; | |
145 | print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0; | |
146 | } | |
147 | } elsif ($WHAT eq '-pkcs12' ) { | |
148 | my $cname = $ARGV[1]; | |
149 | $cname = "My Certificate" unless defined $cname; | |
150 | $RET = run("$PKCS12 -in $NEWCERT -inkey $NEWKEY" | |
151 | . " -certfile ${CATOP}/$CACERT" | |
152 | . " -out $NEWP12" | |
153 | . " -export -name \"$cname\""); | |
154 | print "PKCS #12 file is in $NEWP12\n" if $RET == 0; | |
155 | } elsif ($WHAT eq '-xsign' ) { | |
156 | $RET = run("$CA -policy policy_anything -infiles $NEWREQ"); | |
157 | } elsif ($WHAT eq '-sign' ) { | |
158 | $RET = run("$CA -policy policy_anything -out $NEWCERT -infiles $NEWREQ"); | |
159 | print "Signed certificate is in $NEWCERT\n" if $RET == 0; | |
160 | } elsif ($WHAT eq '-signCA' ) { | |
161 | $RET = run("$CA -policy policy_anything -out $NEWCERT" | |
162 | . " -extensions v3_ca -infiles $NEWREQ"); | |
163 | print "Signed CA certificate is in $NEWCERT\n" if $RET == 0; | |
164 | } elsif ($WHAT eq '-signcert' ) { | |
165 | $RET = run("$X509 -x509toreq -in $NEWREQ -signkey $NEWREQ" | |
166 | . " -out tmp.pem"); | |
167 | $RET = run("$CA -policy policy_anything -out $NEWCERT" | |
168 | . " -infiles tmp.pem") if $RET == 0; | |
169 | print "Signed certificate is in $NEWCERT\n" if $RET == 0; | |
170 | } elsif ($WHAT eq '-verify' ) { | |
33fbca83 RS |
171 | my @files = @ARGV ? @ARGV : ( $NEWCERT ); |
172 | my $file; | |
5a3aa852 | 173 | foreach $file (@files) { |
ac33c5a4 | 174 | my $status = run("$VERIFY \"-CAfile\" ${CATOP}/$CACERT $file"); |
5a3aa852 RS |
175 | $RET = $status if $status != 0; |
176 | } | |
177 | } elsif ($WHAT eq '-crl' ) { | |
178 | $RET = run("$CA -gencrl -out ${CATOP}/crl/$CACRL"); | |
179 | print "Generated CRL is in ${CATOP}/crl/$CACRL\n" if $RET == 0; | |
180 | } elsif ($WHAT eq '-revoke' ) { | |
181 | my $cname = $ARGV[1]; | |
182 | if (!defined $cname) { | |
183 | print "Certificate filename is required; reason optional.\n"; | |
184 | exit 1; | |
185 | } | |
186 | my $reason = $ARGV[2]; | |
187 | $reason = " -crl_reason $reason" | |
188 | if defined $reason && crl_reason_ok($reason); | |
189 | $RET = run("$CA -revoke \"$cname\"" . $reason); | |
190 | } else { | |
191 | print STDERR "Unknown arg \"$WHAT\"\n"; | |
192 | print STDERR "Use -help for help.\n"; | |
193 | exit 1; | |
8f3e97ba | 194 | } |
195 | ||
5a3aa852 | 196 | exit $RET; |