1*4757b351SPierre Pronchery#!/usr/local/bin/perl 2*4757b351SPierre Pronchery# Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. 3*4757b351SPierre Pronchery# 4*4757b351SPierre Pronchery# Licensed under the Apache License 2.0 (the "License"). You may not use 5*4757b351SPierre Pronchery# this file except in compliance with the License. You can obtain a copy 6*4757b351SPierre Pronchery# in the file LICENSE in the source distribution or at 7*4757b351SPierre Pronchery# https://www.openssl.org/source/license.html 8*4757b351SPierre Pronchery 9*4757b351SPierre Pronchery# 10*4757b351SPierre Pronchery# Wrapper around the ca to make it easier to use 11*4757b351SPierre Pronchery# 12*4757b351SPierre Pronchery# WARNING: do not edit! 13*4757b351SPierre Pronchery# Generated by Makefile from apps/CA.pl.in 14*4757b351SPierre Pronchery 15*4757b351SPierre Proncheryuse strict; 16*4757b351SPierre Proncheryuse warnings; 17*4757b351SPierre Pronchery 18*4757b351SPierre Proncherymy $verbose = 1; 19*4757b351SPierre Proncherymy @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify"); 20*4757b351SPierre Pronchery 21*4757b351SPierre Proncherymy $openssl = $ENV{'OPENSSL'} // "openssl"; 22*4757b351SPierre Pronchery$ENV{'OPENSSL'} = $openssl; 23*4757b351SPierre Proncherymy @openssl = split_val($openssl); 24*4757b351SPierre Pronchery 25*4757b351SPierre Proncherymy $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} // ""; 26*4757b351SPierre Proncherymy @OPENSSL_CONFIG = split_val($OPENSSL_CONFIG); 27*4757b351SPierre Pronchery 28*4757b351SPierre Pronchery# Command invocations. 29*4757b351SPierre Proncherymy @REQ = (@openssl, "req", @OPENSSL_CONFIG); 30*4757b351SPierre Proncherymy @CA = (@openssl, "ca", @OPENSSL_CONFIG); 31*4757b351SPierre Proncherymy @VERIFY = (@openssl, "verify"); 32*4757b351SPierre Proncherymy @X509 = (@openssl, "x509"); 33*4757b351SPierre Proncherymy @PKCS12 = (@openssl, "pkcs12"); 34*4757b351SPierre Pronchery 35*4757b351SPierre Pronchery# Default values for various configuration settings. 36*4757b351SPierre Proncherymy $CATOP = "./demoCA"; 37*4757b351SPierre Proncherymy $CAKEY = "cakey.pem"; 38*4757b351SPierre Proncherymy $CAREQ = "careq.pem"; 39*4757b351SPierre Proncherymy $CACERT = "cacert.pem"; 40*4757b351SPierre Proncherymy $CACRL = "crl.pem"; 41*4757b351SPierre Proncherymy @DAYS = qw(-days 365); 42*4757b351SPierre Proncherymy @CADAYS = qw(-days 1095); # 3 years 43*4757b351SPierre Proncherymy @EXTENSIONS = qw(-extensions v3_ca); 44*4757b351SPierre Proncherymy @POLICY = qw(-policy policy_anything); 45*4757b351SPierre Proncherymy $NEWKEY = "newkey.pem"; 46*4757b351SPierre Proncherymy $NEWREQ = "newreq.pem"; 47*4757b351SPierre Proncherymy $NEWCERT = "newcert.pem"; 48*4757b351SPierre Proncherymy $NEWP12 = "newcert.p12"; 49*4757b351SPierre Pronchery 50*4757b351SPierre Pronchery# Commandline parsing 51*4757b351SPierre Proncherymy %EXTRA; 52*4757b351SPierre Proncherymy $WHAT = shift @ARGV // ""; 53*4757b351SPierre Pronchery@ARGV = parse_extra(@ARGV); 54*4757b351SPierre Proncherymy $RET = 0; 55*4757b351SPierre Pronchery 56*4757b351SPierre Proncherysub split_val { 57*4757b351SPierre Pronchery return split_val_win32(@_) if ($^O eq 'MSWin32'); 58*4757b351SPierre Pronchery my ($val) = @_; 59*4757b351SPierre Pronchery my (@ret, @frag); 60*4757b351SPierre Pronchery 61*4757b351SPierre Pronchery # Skip leading whitespace 62*4757b351SPierre Pronchery $val =~ m{\A[ \t]*}ogc; 63*4757b351SPierre Pronchery 64*4757b351SPierre Pronchery # Unix shell-compatible split 65*4757b351SPierre Pronchery # 66*4757b351SPierre Pronchery # Handles backslash escapes outside quotes and 67*4757b351SPierre Pronchery # in double-quoted strings. Parameter and 68*4757b351SPierre Pronchery # command-substitution is silently ignored. 69*4757b351SPierre Pronchery # Bare newlines outside quotes and (trailing) backslashes are disallowed. 70*4757b351SPierre Pronchery 71*4757b351SPierre Pronchery while (1) { 72*4757b351SPierre Pronchery last if (pos($val) == length($val)); 73*4757b351SPierre Pronchery 74*4757b351SPierre Pronchery # The first char is never a SPACE or TAB. Possible matches are: 75*4757b351SPierre Pronchery # 1. Ordinary string fragment 76*4757b351SPierre Pronchery # 2. Single-quoted string 77*4757b351SPierre Pronchery # 3. Double-quoted string 78*4757b351SPierre Pronchery # 4. Backslash escape 79*4757b351SPierre Pronchery # 5. Bare backlash or newline (rejected) 80*4757b351SPierre Pronchery # 81*4757b351SPierre Pronchery if ($val =~ m{\G([^'" \t\n\\]+)}ogc) { 82*4757b351SPierre Pronchery # Ordinary string 83*4757b351SPierre Pronchery push @frag, $1; 84*4757b351SPierre Pronchery } elsif ($val =~ m{\G'([^']*)'}ogc) { 85*4757b351SPierre Pronchery # Single-quoted string 86*4757b351SPierre Pronchery push @frag, $1; 87*4757b351SPierre Pronchery } elsif ($val =~ m{\G"}ogc) { 88*4757b351SPierre Pronchery # Double-quoted string 89*4757b351SPierre Pronchery push @frag, ""; 90*4757b351SPierre Pronchery while (1) { 91*4757b351SPierre Pronchery last if ($val =~ m{\G"}ogc); 92*4757b351SPierre Pronchery if ($val =~ m{\G([^"\\]+)}ogcs) { 93*4757b351SPierre Pronchery # literals 94*4757b351SPierre Pronchery push @frag, $1; 95*4757b351SPierre Pronchery } elsif ($val =~ m{\G.(["\`\$\\])}ogc) { 96*4757b351SPierre Pronchery # backslash-escaped special 97*4757b351SPierre Pronchery push @frag, $1; 98*4757b351SPierre Pronchery } elsif ($val =~ m{\G.(.)}ogcs) { 99*4757b351SPierre Pronchery # backslashed non-special 100*4757b351SPierre Pronchery push @frag, "\\$1" unless $1 eq "\n"; 101*4757b351SPierre Pronchery } else { 102*4757b351SPierre Pronchery die sprintf("Malformed quoted string: %s\n", $val); 103*4757b351SPierre Pronchery } 104*4757b351SPierre Pronchery } 105*4757b351SPierre Pronchery } elsif ($val =~ m{\G\\(.)}ogc) { 106*4757b351SPierre Pronchery # Backslash is unconditional escape outside quoted strings 107*4757b351SPierre Pronchery push @frag, $1 unless $1 eq "\n"; 108*4757b351SPierre Pronchery } else { 109*4757b351SPierre Pronchery die sprintf("Bare backslash or newline in: '%s'\n", $val); 110*4757b351SPierre Pronchery } 111*4757b351SPierre Pronchery # Done if at SPACE, TAB or end, otherwise continue current fragment 112*4757b351SPierre Pronchery # 113*4757b351SPierre Pronchery next unless ($val =~ m{\G(?:[ \t]+|\z)}ogcs); 114*4757b351SPierre Pronchery push @ret, join("", splice(@frag)) if (@frag > 0); 115*4757b351SPierre Pronchery } 116*4757b351SPierre Pronchery # Handle final fragment 117*4757b351SPierre Pronchery push @ret, join("", splice(@frag)) if (@frag > 0); 118*4757b351SPierre Pronchery return @ret; 119*4757b351SPierre Pronchery} 120*4757b351SPierre Pronchery 121*4757b351SPierre Proncherysub split_val_win32 { 122*4757b351SPierre Pronchery my ($val) = @_; 123*4757b351SPierre Pronchery my (@ret, @frag); 124*4757b351SPierre Pronchery 125*4757b351SPierre Pronchery # Skip leading whitespace 126*4757b351SPierre Pronchery $val =~ m{\A[ \t]*}ogc; 127*4757b351SPierre Pronchery 128*4757b351SPierre Pronchery # Windows-compatible split 129*4757b351SPierre Pronchery # See: "Parsing C++ command-line arguments" in: 130*4757b351SPierre Pronchery # https://learn.microsoft.com/en-us/cpp/cpp/main-function-command-line-args?view=msvc-170 131*4757b351SPierre Pronchery # 132*4757b351SPierre Pronchery # Backslashes are special only when followed by a double-quote 133*4757b351SPierre Pronchery # Pairs of double-quotes make a single double-quote. 134*4757b351SPierre Pronchery # Closing double-quotes may be omitted. 135*4757b351SPierre Pronchery 136*4757b351SPierre Pronchery while (1) { 137*4757b351SPierre Pronchery last if (pos($val) == length($val)); 138*4757b351SPierre Pronchery 139*4757b351SPierre Pronchery # The first char is never a SPACE or TAB. 140*4757b351SPierre Pronchery # 1. Ordinary string fragment 141*4757b351SPierre Pronchery # 2. Double-quoted string 142*4757b351SPierre Pronchery # 3. Backslashes preceding a double-quote 143*4757b351SPierre Pronchery # 4. Literal backslashes 144*4757b351SPierre Pronchery # 5. Bare newline (rejected) 145*4757b351SPierre Pronchery # 146*4757b351SPierre Pronchery if ($val =~ m{\G([^" \t\n\\]+)}ogc) { 147*4757b351SPierre Pronchery # Ordinary string 148*4757b351SPierre Pronchery push @frag, $1; 149*4757b351SPierre Pronchery } elsif ($val =~ m{\G"}ogc) { 150*4757b351SPierre Pronchery # Double-quoted string 151*4757b351SPierre Pronchery push @frag, ""; 152*4757b351SPierre Pronchery while (1) { 153*4757b351SPierre Pronchery if ($val =~ m{\G("+)}ogc) { 154*4757b351SPierre Pronchery # Two double-quotes make one literal double-quote 155*4757b351SPierre Pronchery my $l = length($1); 156*4757b351SPierre Pronchery push @frag, q{"} x int($l/2) if ($l > 1); 157*4757b351SPierre Pronchery next if ($l % 2 == 0); 158*4757b351SPierre Pronchery last; 159*4757b351SPierre Pronchery } 160*4757b351SPierre Pronchery if ($val =~ m{\G([^"\\]+)}ogc) { 161*4757b351SPierre Pronchery push @frag, $1; 162*4757b351SPierre Pronchery } elsif ($val =~ m{\G((?>[\\]+))(?=")}ogc) { 163*4757b351SPierre Pronchery # Backslashes before a double-quote are escapes 164*4757b351SPierre Pronchery my $l = length($1); 165*4757b351SPierre Pronchery push @frag, q{\\} x int($l / 2); 166*4757b351SPierre Pronchery if ($l % 2 == 1) { 167*4757b351SPierre Pronchery ++pos($val); 168*4757b351SPierre Pronchery push @frag, q{"}; 169*4757b351SPierre Pronchery } 170*4757b351SPierre Pronchery } elsif ($val =~ m{\G((?:(?>[\\]+)[^"\\]+)+)}ogc) { 171*4757b351SPierre Pronchery # Backslashes not before a double-quote are not special 172*4757b351SPierre Pronchery push @frag, $1; 173*4757b351SPierre Pronchery } else { 174*4757b351SPierre Pronchery # Tolerate missing closing double-quote 175*4757b351SPierre Pronchery last; 176*4757b351SPierre Pronchery } 177*4757b351SPierre Pronchery } 178*4757b351SPierre Pronchery } elsif ($val =~ m{\G((?>[\\]+))(?=")}ogc) { 179*4757b351SPierre Pronchery my $l = length($1); 180*4757b351SPierre Pronchery push @frag, q{\\} x int($l / 2); 181*4757b351SPierre Pronchery if ($l % 2 == 1) { 182*4757b351SPierre Pronchery ++pos($val); 183*4757b351SPierre Pronchery push @frag, q{"}; 184*4757b351SPierre Pronchery } 185*4757b351SPierre Pronchery } elsif ($val =~ m{\G([\\]+)}ogc) { 186*4757b351SPierre Pronchery # Backslashes not before a double-quote are not special 187*4757b351SPierre Pronchery push @frag, $1; 188*4757b351SPierre Pronchery } else { 189*4757b351SPierre Pronchery die sprintf("Bare newline in: '%s'\n", $val); 190*4757b351SPierre Pronchery } 191*4757b351SPierre Pronchery # Done if at SPACE, TAB or end, otherwise continue current fragment 192*4757b351SPierre Pronchery # 193*4757b351SPierre Pronchery next unless ($val =~ m{\G(?:[ \t]+|\z)}ogcs); 194*4757b351SPierre Pronchery push @ret, join("", splice(@frag)) if (@frag > 0); 195*4757b351SPierre Pronchery } 196*4757b351SPierre Pronchery # Handle final fragment 197*4757b351SPierre Pronchery push @ret, join("", splice(@frag)) if (@frag); 198*4757b351SPierre Pronchery return @ret; 199*4757b351SPierre Pronchery} 200*4757b351SPierre Pronchery 201*4757b351SPierre Pronchery# Split out "-extra-CMD value", and return new |@ARGV|. Fill in 202*4757b351SPierre Pronchery# |EXTRA{CMD}| with list of values. 203*4757b351SPierre Proncherysub parse_extra 204*4757b351SPierre Pronchery{ 205*4757b351SPierre Pronchery my @args; 206*4757b351SPierre Pronchery foreach ( @OPENSSL_CMDS ) { 207*4757b351SPierre Pronchery $EXTRA{$_} = []; 208*4757b351SPierre Pronchery } 209*4757b351SPierre Pronchery while (@_) { 210*4757b351SPierre Pronchery my $arg = shift(@_); 211*4757b351SPierre Pronchery if ( $arg !~ m{^-extra-(\w+)$} ) { 212*4757b351SPierre Pronchery push @args, split_val($arg); 213*4757b351SPierre Pronchery next; 214*4757b351SPierre Pronchery } 215*4757b351SPierre Pronchery $arg = $1; 216*4757b351SPierre Pronchery die "Unknown \"-extra-${arg}\" option, exiting\n" 217*4757b351SPierre Pronchery unless grep { $arg eq $_ } @OPENSSL_CMDS; 218*4757b351SPierre Pronchery die "Missing \"-extra-${arg}\" option value, exiting\n" 219*4757b351SPierre Pronchery unless (@_ > 0); 220*4757b351SPierre Pronchery push @{$EXTRA{$arg}}, split_val(shift(@_)); 221*4757b351SPierre Pronchery } 222*4757b351SPierre Pronchery return @args; 223*4757b351SPierre Pronchery} 224*4757b351SPierre Pronchery 225*4757b351SPierre Pronchery 226*4757b351SPierre Pronchery# See if reason for a CRL entry is valid; exit if not. 227*4757b351SPierre Proncherysub crl_reason_ok 228*4757b351SPierre Pronchery{ 229*4757b351SPierre Pronchery my $r = shift; 230*4757b351SPierre Pronchery 231*4757b351SPierre Pronchery if ($r eq 'unspecified' || $r eq 'keyCompromise' 232*4757b351SPierre Pronchery || $r eq 'CACompromise' || $r eq 'affiliationChanged' 233*4757b351SPierre Pronchery || $r eq 'superseded' || $r eq 'cessationOfOperation' 234*4757b351SPierre Pronchery || $r eq 'certificateHold' || $r eq 'removeFromCRL') { 235*4757b351SPierre Pronchery return 1; 236*4757b351SPierre Pronchery } 237*4757b351SPierre Pronchery print STDERR "Invalid CRL reason; must be one of:\n"; 238*4757b351SPierre Pronchery print STDERR " unspecified, keyCompromise, CACompromise,\n"; 239*4757b351SPierre Pronchery print STDERR " affiliationChanged, superseded, cessationOfOperation\n"; 240*4757b351SPierre Pronchery print STDERR " certificateHold, removeFromCRL"; 241*4757b351SPierre Pronchery exit 1; 242*4757b351SPierre Pronchery} 243*4757b351SPierre Pronchery 244*4757b351SPierre Pronchery# Copy a PEM-format file; return like exit status (zero means ok) 245*4757b351SPierre Proncherysub copy_pemfile 246*4757b351SPierre Pronchery{ 247*4757b351SPierre Pronchery my ($infile, $outfile, $bound) = @_; 248*4757b351SPierre Pronchery my $found = 0; 249*4757b351SPierre Pronchery 250*4757b351SPierre Pronchery open IN, $infile || die "Cannot open $infile, $!"; 251*4757b351SPierre Pronchery open OUT, ">$outfile" || die "Cannot write to $outfile, $!"; 252*4757b351SPierre Pronchery while (<IN>) { 253*4757b351SPierre Pronchery $found = 1 if /^-----BEGIN.*$bound/; 254*4757b351SPierre Pronchery print OUT $_ if $found; 255*4757b351SPierre Pronchery $found = 2, last if /^-----END.*$bound/; 256*4757b351SPierre Pronchery } 257*4757b351SPierre Pronchery close IN; 258*4757b351SPierre Pronchery close OUT; 259*4757b351SPierre Pronchery return $found == 2 ? 0 : 1; 260*4757b351SPierre Pronchery} 261*4757b351SPierre Pronchery 262*4757b351SPierre Pronchery# Wrapper around system; useful for debugging. Returns just the exit status 263*4757b351SPierre Proncherysub run 264*4757b351SPierre Pronchery{ 265*4757b351SPierre Pronchery my ($cmd, @args) = @_; 266*4757b351SPierre Pronchery print "====\n$cmd @args\n" if $verbose; 267*4757b351SPierre Pronchery my $status = system {$cmd} $cmd, @args; 268*4757b351SPierre Pronchery print "==> $status\n====\n" if $verbose; 269*4757b351SPierre Pronchery return $status >> 8; 270*4757b351SPierre Pronchery} 271*4757b351SPierre Pronchery 272*4757b351SPierre Pronchery 273*4757b351SPierre Proncheryif ( $WHAT =~ /^(-\?|-h|-help)$/ ) { 274*4757b351SPierre Pronchery print STDERR <<EOF; 275*4757b351SPierre ProncheryUsage: 276*4757b351SPierre Pronchery CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd parameter] 277*4757b351SPierre Pronchery CA.pl -pkcs12 [certname] 278*4757b351SPierre Pronchery CA.pl -verify certfile ... 279*4757b351SPierre Pronchery CA.pl -revoke certfile [reason] 280*4757b351SPierre ProncheryEOF 281*4757b351SPierre Pronchery exit 0; 282*4757b351SPierre Pronchery} 283*4757b351SPierre Pronchery 284*4757b351SPierre Proncheryif ($WHAT eq '-newcert' ) { 285*4757b351SPierre Pronchery # create a certificate 286*4757b351SPierre Pronchery $RET = run(@REQ, qw(-new -x509 -keyout), $NEWKEY, "-out", $NEWCERT, @DAYS, @{$EXTRA{req}}); 287*4757b351SPierre Pronchery print "Cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0; 288*4757b351SPierre Pronchery} elsif ($WHAT eq '-precert' ) { 289*4757b351SPierre Pronchery # create a pre-certificate 290*4757b351SPierre Pronchery $RET = run(@REQ, qw(-x509 -precert -keyout), $NEWKEY, "-out", $NEWCERT, @DAYS, @{$EXTRA{req}}); 291*4757b351SPierre Pronchery print "Pre-cert is in $NEWCERT, private key is in $NEWKEY\n" if $RET == 0; 292*4757b351SPierre Pronchery} elsif ($WHAT =~ /^\-newreq(\-nodes)?$/ ) { 293*4757b351SPierre Pronchery # create a certificate request 294*4757b351SPierre Pronchery $RET = run(@REQ, "-new", (defined $1 ? ($1,) : ()), "-keyout", $NEWKEY, "-out", $NEWREQ, @{$EXTRA{req}}); 295*4757b351SPierre Pronchery print "Request is in $NEWREQ, private key is in $NEWKEY\n" if $RET == 0; 296*4757b351SPierre Pronchery} elsif ($WHAT eq '-newca' ) { 297*4757b351SPierre Pronchery # create the directory hierarchy 298*4757b351SPierre Pronchery my @dirs = ( "${CATOP}", "${CATOP}/certs", "${CATOP}/crl", 299*4757b351SPierre Pronchery "${CATOP}/newcerts", "${CATOP}/private" ); 300*4757b351SPierre Pronchery die "${CATOP}/index.txt exists.\nRemove old sub-tree to proceed," 301*4757b351SPierre Pronchery if -f "${CATOP}/index.txt"; 302*4757b351SPierre Pronchery die "${CATOP}/serial exists.\nRemove old sub-tree to proceed," 303*4757b351SPierre Pronchery if -f "${CATOP}/serial"; 304*4757b351SPierre Pronchery foreach my $d ( @dirs ) { 305*4757b351SPierre Pronchery if ( -d $d ) { 306*4757b351SPierre Pronchery warn "Directory $d exists" if -d $d; 307*4757b351SPierre Pronchery } else { 308*4757b351SPierre Pronchery mkdir $d or die "Can't mkdir $d, $!"; 309*4757b351SPierre Pronchery } 310*4757b351SPierre Pronchery } 311*4757b351SPierre Pronchery 312*4757b351SPierre Pronchery open OUT, ">${CATOP}/index.txt"; 313*4757b351SPierre Pronchery close OUT; 314*4757b351SPierre Pronchery open OUT, ">${CATOP}/crlnumber"; 315*4757b351SPierre Pronchery print OUT "01\n"; 316*4757b351SPierre Pronchery close OUT; 317*4757b351SPierre Pronchery # ask user for existing CA certificate 318*4757b351SPierre Pronchery print "CA certificate filename (or enter to create)\n"; 319*4757b351SPierre Pronchery my $FILE; 320*4757b351SPierre Pronchery $FILE = "" unless defined($FILE = <STDIN>); 321*4757b351SPierre Pronchery $FILE =~ s{\R$}{}; 322*4757b351SPierre Pronchery if ($FILE ne "") { 323*4757b351SPierre Pronchery copy_pemfile($FILE,"${CATOP}/private/$CAKEY", "PRIVATE"); 324*4757b351SPierre Pronchery copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); 325*4757b351SPierre Pronchery } else { 326*4757b351SPierre Pronchery print "Making CA certificate ...\n"; 327*4757b351SPierre Pronchery $RET = run(@REQ, qw(-new -keyout), "${CATOP}/private/$CAKEY", 328*4757b351SPierre Pronchery "-out", "${CATOP}/$CAREQ", @{$EXTRA{req}}); 329*4757b351SPierre Pronchery $RET = run(@CA, qw(-create_serial -out), "${CATOP}/$CACERT", @CADAYS, 330*4757b351SPierre Pronchery qw(-batch -keyfile), "${CATOP}/private/$CAKEY", "-selfsign", 331*4757b351SPierre Pronchery @EXTENSIONS, "-infiles", "${CATOP}/$CAREQ", @{$EXTRA{ca}}) 332*4757b351SPierre Pronchery if $RET == 0; 333*4757b351SPierre Pronchery print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0; 334*4757b351SPierre Pronchery } 335*4757b351SPierre Pronchery} elsif ($WHAT eq '-pkcs12' ) { 336*4757b351SPierre Pronchery my $cname = $ARGV[0]; 337*4757b351SPierre Pronchery $cname = "My Certificate" unless defined $cname; 338*4757b351SPierre Pronchery $RET = run(@PKCS12, "-in", $NEWCERT, "-inkey", $NEWKEY, 339*4757b351SPierre Pronchery "-certfile", "${CATOP}/$CACERT", "-out", $NEWP12, 340*4757b351SPierre Pronchery qw(-export -name), $cname, @{$EXTRA{pkcs12}}); 341*4757b351SPierre Pronchery print "PKCS#12 file is in $NEWP12\n" if $RET == 0; 342*4757b351SPierre Pronchery} elsif ($WHAT eq '-xsign' ) { 343*4757b351SPierre Pronchery $RET = run(@CA, @POLICY, "-infiles", $NEWREQ, @{$EXTRA{ca}}); 344*4757b351SPierre Pronchery} elsif ($WHAT eq '-sign' ) { 345*4757b351SPierre Pronchery $RET = run(@CA, @POLICY, "-out", $NEWCERT, 346*4757b351SPierre Pronchery "-infiles", $NEWREQ, @{$EXTRA{ca}}); 347*4757b351SPierre Pronchery print "Signed certificate is in $NEWCERT\n" if $RET == 0; 348*4757b351SPierre Pronchery} elsif ($WHAT eq '-signCA' ) { 349*4757b351SPierre Pronchery $RET = run(@CA, @POLICY, "-out", $NEWCERT, @EXTENSIONS, 350*4757b351SPierre Pronchery "-infiles", $NEWREQ, @{$EXTRA{ca}}); 351*4757b351SPierre Pronchery print "Signed CA certificate is in $NEWCERT\n" if $RET == 0; 352*4757b351SPierre Pronchery} elsif ($WHAT eq '-signcert' ) { 353*4757b351SPierre Pronchery $RET = run(@X509, qw(-x509toreq -in), $NEWREQ, "-signkey", $NEWREQ, 354*4757b351SPierre Pronchery qw(-out tmp.pem), @{$EXTRA{x509}}); 355*4757b351SPierre Pronchery $RET = run(@CA, @POLICY, "-out", $NEWCERT, 356*4757b351SPierre Pronchery qw(-infiles tmp.pem), @{$EXTRA{ca}}) if $RET == 0; 357*4757b351SPierre Pronchery print "Signed certificate is in $NEWCERT\n" if $RET == 0; 358*4757b351SPierre Pronchery} elsif ($WHAT eq '-verify' ) { 359*4757b351SPierre Pronchery my @files = @ARGV ? @ARGV : ( $NEWCERT ); 360*4757b351SPierre Pronchery foreach my $file (@files) { 361*4757b351SPierre Pronchery my $status = run(@VERIFY, "-CAfile", "${CATOP}/$CACERT", $file, @{$EXTRA{verify}}); 362*4757b351SPierre Pronchery $RET = $status if $status != 0; 363*4757b351SPierre Pronchery } 364*4757b351SPierre Pronchery} elsif ($WHAT eq '-crl' ) { 365*4757b351SPierre Pronchery $RET = run(@CA, qw(-gencrl -out), "${CATOP}/crl/$CACRL", @{$EXTRA{ca}}); 366*4757b351SPierre Pronchery print "Generated CRL is in ${CATOP}/crl/$CACRL\n" if $RET == 0; 367*4757b351SPierre Pronchery} elsif ($WHAT eq '-revoke' ) { 368*4757b351SPierre Pronchery my $cname = $ARGV[0]; 369*4757b351SPierre Pronchery if (!defined $cname) { 370*4757b351SPierre Pronchery print "Certificate filename is required; reason optional.\n"; 371*4757b351SPierre Pronchery exit 1; 372*4757b351SPierre Pronchery } 373*4757b351SPierre Pronchery my @reason; 374*4757b351SPierre Pronchery @reason = ("-crl_reason", $ARGV[1]) 375*4757b351SPierre Pronchery if defined $ARGV[1] && crl_reason_ok($ARGV[1]); 376*4757b351SPierre Pronchery $RET = run(@CA, "-revoke", $cname, @reason, @{$EXTRA{ca}}); 377*4757b351SPierre Pronchery} else { 378*4757b351SPierre Pronchery print STDERR "Unknown arg \"$WHAT\"\n"; 379*4757b351SPierre Pronchery print STDERR "Use -help for help.\n"; 380*4757b351SPierre Pronchery exit 1; 381*4757b351SPierre Pronchery} 382*4757b351SPierre Pronchery 383*4757b351SPierre Proncheryexit $RET; 384