From cab33afb711e467f459e5b5e669bf7a5c4fe797a Mon Sep 17 00:00:00 2001 From: Rich Salz Date: Mon, 16 Mar 2020 15:53:00 -0400 Subject: [PATCH] Update CA.pl podpage, and script Merge the NOTES section into the relevant parts of the manpage. Add the $EXTRA parameter in consistent places (the end) to call commands. Document that multiple -extra-XXX might be needed. Reviewed-by: Tomas Mraz Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/11338) --- apps/CA.pl.in | 130 ++++++++++++++++++++++++++------------------- doc/man1/CA.pl.pod | 96 ++++++++++++--------------------- 2 files changed, 110 insertions(+), 116 deletions(-) diff --git a/apps/CA.pl.in b/apps/CA.pl.in index 12c9452444..918534d6a1 100644 --- a/apps/CA.pl.in +++ b/apps/CA.pl.in @@ -14,57 +14,63 @@ use strict; use warnings; -my $openssl = "openssl"; -if(defined $ENV{'OPENSSL'}) { - $openssl = $ENV{'OPENSSL'}; -} else { - $ENV{'OPENSSL'} = $openssl; -} - my $verbose = 1; +my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify"); -my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} || ""; -my $DAYS = "-days 365"; -my $CADAYS = "-days 1095"; # 3 years +my $openssl = $ENV{'OPENSSL'} // "openssl"; +$ENV{'OPENSSL'} = $openssl; +my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} // ""; + +# Command invocations. my $REQ = "$openssl req $OPENSSL_CONFIG"; my $CA = "$openssl ca $OPENSSL_CONFIG"; my $VERIFY = "$openssl verify"; my $X509 = "$openssl x509"; my $PKCS12 = "$openssl pkcs12"; -# default openssl.cnf file has setup as per the following +# Default values for various configuration settings. my $CATOP = "./demoCA"; my $CAKEY = "cakey.pem"; my $CAREQ = "careq.pem"; my $CACERT = "cacert.pem"; my $CACRL = "crl.pem"; -my $DIRMODE = 0777; - +my $DAYS = "-days 365"; +my $CADAYS = "-days 1095"; # 3 years my $NEWKEY = "newkey.pem"; my $NEWREQ = "newreq.pem"; my $NEWCERT = "newcert.pem"; my $NEWP12 = "newcert.p12"; -my $RET = 0; + +# Commandline parsing +my %EXTRA; my $WHAT = shift @ARGV || ""; -my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify"); -my %EXTRA = extra_args(\@ARGV, "-extra-"); -my $FILE; - -sub extra_args { - my ($args_ref, $arg_prefix) = @_; - my %eargs = map { - if ($_ < $#$args_ref) { - my ($arg, $value) = splice(@$args_ref, $_, 2); - $arg =~ s/$arg_prefix//; - ($arg, $value); - } else { - (); - } - } reverse grep($$args_ref[$_] =~ /$arg_prefix/, 0..$#$args_ref); - my %empty = map { ($_, "") } @OPENSSL_CMDS; - return (%empty, %eargs); +@ARGV = parse_extra(@ARGV); +my $RET = 0; + +# Split out "-extra-CMD value", and return new |@ARGV|. Fill in +# |EXTRA{CMD}| with list of values. +sub parse_extra +{ + foreach ( @OPENSSL_CMDS ) { + $EXTRA{$_} = ''; + } + + my @result; + while ( scalar(@_) > 0 ) { + my $arg = shift; + if ( $arg !~ m/-extra-([a-z0-9]+)/ ) { + push @result, $arg; + next; + } + $arg =~ s/-extra-//; + die("Unknown \"-${arg}-extra\" option, exiting") + unless scalar grep { $arg eq $_ } @OPENSSL_CMDS; + $EXTRA{$arg} .= " " . shift; + } + return @result; } + # See if reason for a CRL entry is valid; exit if not. sub crl_reason_ok { @@ -113,19 +119,25 @@ sub run if ( $WHAT =~ /^(-\?|-h|-help)$/ ) { - print STDERR "usage: CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd extra-params]\n"; - print STDERR " CA.pl -pkcs12 [-extra-pkcs12 extra-params] [certname]\n"; - print STDERR " CA.pl -verify [-extra-verify extra-params] certfile ...\n"; - print STDERR " CA.pl -revoke [-extra-ca extra-params] certfile [reason]\n"; + print STDERR <${CATOP}/index.txt"; close OUT; open OUT, ">${CATOP}/crlnumber"; @@ -145,6 +166,7 @@ if ($WHAT eq '-newcert' ) { close OUT; # ask user for existing CA certificate print "CA certificate filename (or enter to create)\n"; + my $FILE; $FILE = "" unless defined($FILE = ); $FILE =~ s{\R$}{}; if ($FILE ne "") { @@ -152,44 +174,42 @@ if ($WHAT eq '-newcert' ) { copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); } else { print "Making CA certificate ...\n"; - $RET = run("$REQ -new -keyout" - . " ${CATOP}/private/$CAKEY" + $RET = run("$REQ -new -keyout ${CATOP}/private/$CAKEY" . " -out ${CATOP}/$CAREQ $EXTRA{req}"); $RET = run("$CA -create_serial" . " -out ${CATOP}/$CACERT $CADAYS -batch" . " -keyfile ${CATOP}/private/$CAKEY -selfsign" - . " -extensions v3_ca $EXTRA{ca}" - . " -infiles ${CATOP}/$CAREQ") if $RET == 0; + . " -extensions v3_ca" + . " -infiles ${CATOP}/$CAREQ $EXTRA{ca}") if $RET == 0; print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0; } } elsif ($WHAT eq '-pkcs12' ) { my $cname = $ARGV[0]; $cname = "My Certificate" unless defined $cname; $RET = run("$PKCS12 -in $NEWCERT -inkey $NEWKEY" - . " -certfile ${CATOP}/$CACERT" - . " -out $NEWP12" + . " -certfile ${CATOP}/$CACERT -out $NEWP12" . " -export -name \"$cname\" $EXTRA{pkcs12}"); print "PKCS #12 file is in $NEWP12\n" if $RET == 0; } elsif ($WHAT eq '-xsign' ) { - $RET = run("$CA -policy policy_anything $EXTRA{ca} -infiles $NEWREQ"); + $RET = run("$CA -policy policy_anything -infiles $NEWREQ $EXTRA{ca}"); } elsif ($WHAT eq '-sign' ) { - $RET = run("$CA -policy policy_anything -out $NEWCERT $EXTRA{ca} -infiles $NEWREQ"); + $RET = run("$CA -policy policy_anything -out $NEWCERT" + . " -infiles $NEWREQ $EXTRA{ca}"); print "Signed certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-signCA' ) { $RET = run("$CA -policy policy_anything -out $NEWCERT" - . " -extensions v3_ca $EXTRA{ca} -infiles $NEWREQ"); + . " -extensions v3_ca -infiles $NEWREQ $EXTRA{ca}"); print "Signed CA certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-signcert' ) { $RET = run("$X509 -x509toreq -in $NEWREQ -signkey $NEWREQ" . " -out tmp.pem $EXTRA{x509}"); $RET = run("$CA -policy policy_anything -out $NEWCERT" - . "$EXTRA{ca} -infiles tmp.pem") if $RET == 0; + . "-infiles tmp.pem $EXTRA{ca}") if $RET == 0; print "Signed certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-verify' ) { my @files = @ARGV ? @ARGV : ( $NEWCERT ); - my $file; - foreach $file (@files) { - my $status = run("$VERIFY \"-CAfile\" ${CATOP}/$CACERT $file $EXTRA{verify}"); + foreach my $file (@files) { + my $status = run("$VERIFY -CAfile ${CATOP}/$CACERT $file $EXTRA{verify}"); $RET = $status if $status != 0; } } elsif ($WHAT eq '-crl' ) { diff --git a/doc/man1/CA.pl.pod b/doc/man1/CA.pl.pod index 4c53970890..fa07c8926c 100644 --- a/doc/man1/CA.pl.pod +++ b/doc/man1/CA.pl.pod @@ -21,13 +21,13 @@ B<-signCA> | B<-signcert> | B<-crl> | B<-newca> -[B<-extra-cmd> I] +[B<-extra-I> I] -B B<-pkcs12> [B<-extra-pkcs12> I] [I] +B B<-pkcs12> [B<-extra-pkcs12> I] [I] -B B<-verify> [B<-extra-verify> I] I ... +B B<-verify> [B<-extra-verify> I] I ... -B B<-revoke> [B<-extra-ca> I] I [I] +B B<-revoke> [B<-extra-ca> I] I [I] =head1 DESCRIPTION @@ -36,6 +36,23 @@ arguments to the L command for some common certificate operations. It is intended to simplify the process of certificate creation and management by the use of some simple options. +The script is intended as a simple front end for the L program for +use by a beginner. Its behaviour isn't always what is wanted. For more control +over the behaviour of the certificate commands call the L command +directly. + +Most of the filenames mentioned below can be modified by editing the +B script. + +Under some environments it may not be possible to run the B script +directly (for example Win32) and the default configuration file location may +be wrong. In this case the command: + + perl -S CA.pl + +can be used and the B environment variable can be set to point to +the correct path of the configuration file. + =head1 OPTIONS =over 4 @@ -70,6 +87,11 @@ details of the CA will be prompted for. The relevant files and directories are created in a directory called F in the current directory. Uses L and L. +If the F directory already exists then the B<-newca> command will not +overwrite it and will do nothing. This can happen if a previous call using +the B<-newca> option terminated abnormally. To get the correct behaviour +delete the directory if it already exists. + =item B<-pkcs12> Create a PKCS#12 file containing the user certificate, private key and CA @@ -120,13 +142,15 @@ Verifies certificates against the CA certificate for F. If no certificates are specified on the command line it tries to verify the file F. Invokes L. -=item B<-extra-req> | B<-extra-ca> | B<-extra-pkcs12> | B<-extra-x509> | B<-extra-verify> I +=item B<-extra-I> I -For each option B>, pass I to the L +For each option B>, pass I to the L sub-command with the same name as I, if that sub-command is invoked. -For example, if L is invoked, the I given with +For example, if L is invoked, the I given with B<-extra-req> will be passed to it. -Users should consult L command documentation for more information. +For multi-word parameters, either repeat the option or quote the I +so it looks like one word to your shell. +See the individual command documentation for more information. =back @@ -144,66 +168,16 @@ the request and finally create a PKCS#12 file containing it. CA.pl -signreq CA.pl -pkcs12 "My Test Certificate" -=head1 DSA CERTIFICATES - -Although the B creates RSA CAs and requests it is still possible to -use it with DSA certificates and requests using the L command -directly. The following example shows the steps that would typically be taken. - -Create some DSA parameters: - - openssl dsaparam -out dsap.pem 1024 - -Create a DSA CA certificate and private key: - - openssl req -x509 -newkey dsa:dsap.pem -keyout cacert.pem -out cacert.pem - -Create the CA directories and files: - - CA.pl -newca - -enter a filename (for example, F) when prompted for the CA file -name. - -Create a DSA certificate request and private key (a different set of parameters -can optionally be created first): - - openssl req -out newreq.pem -newkey dsa:dsap.pem - -Sign the request: - - CA.pl -signreq - =head1 ENVIRONMENT +The environment variable B may be used to specify the name of +the OpenSSL program. It can be a full pathname, or a relative one. + The environment variable B may be used to specify a configuration option and value to the B and B commands invoked by this script. It's value should be the option and pathname, as in C<-config /path/to/conf-file>. -=head1 NOTES - -Most of the filenames mentioned can be modified by editing the B script. - -If the F directory already exists then the B<-newca> command will not -overwrite it and will do nothing. This can happen if a previous call using -the B<-newca> option terminated abnormally. To get the correct behaviour -delete the demoCA directory if it already exists. - -Under some environments it may not be possible to run the B script -directly (for example Win32) and the default configuration file location may -be wrong. In this case the command: - - perl -S CA.pl - -can be used and the B environment variable changed to point to -the correct path of the configuration file. - -The script is intended as a simple front end for the L program for -use by a beginner. Its behaviour isn't always what is wanted. For more control -over the behaviour of the certificate commands call the L command -directly. - =head1 SEE ALSO L, -- 2.34.1