问题
centos-6.8 perl, v5.10.1 (*) built for x86_64-linux-thread-multi
I am attempting to update a Perl script called CSP. My experience with the script is limited to running it on rare occasions when we needed a new server certificate. I contacted the author of the original script, Leif Johansson, but I did not receive a response. The revised project that I am presently working on and refer to below can be found at https://github.com/byrnejb/rcsp/tree/csp040.
That is the background. My programming experience with Perl is negligible. Thus my questions here may be naive.
I have these code fragments in ./blib/lib/CSP.pm
:
. . .
package CSP;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require Exporter;
require AutoLoader;
use IO::File;
use Term::Prompt;
use POSIX qw(strftime);
use Date::Calc qw(Day_of_Week Gmtime Add_Delta_Days Add_Delta_DHMS);
use Sys::Hostname;
@ISA = qw(Exporter AutoLoader);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@EXPORT = qw();
@EXPORT_OK = qw($_openssl);
$VERSION = '0.40';
# Preloaded methods go here.
# Autoload methods go after =cut, and are processed by the autosplit program.
$CSP::_openssl='openssl';
. . .
$CSP::_openssl='openssl';
. . .
sub genkey
{
my $self = shift;
my $args = shift;
$self->die("Required parameter keyfile missing")
unless $args->{keyfile};
$args->{keysize} = 4096 unless $args->{keysize} > 0;
$args->{keypass} = "'" . $self->getPassword("Private key password",1) . "'"
unless $args->{keypass};
$self->warn("# Password argument: $args->{keypass}\n") if $ENV{CSPDEBUG};
my $cmd = "-out $args->{keyfile} $args->{keysize}";
$cmd = "-des3 -passout pass:$args->{keypass} ".$cmd if defined($args->{keypass});
$self->{openssl}->cmd('genrsa',$cmd,$args);
}
## Generate and optionally self-sign the request
my $process;
my $what;
my $common_args = "-$args->{digest} -days $args->{days} ".
" -key $cakey -passin pass:$args->{keypass}";
if ($args->{csrfile})
{
$self->{openssl}->cmd('req',"-new $common_args -out $args->{csrfile}",$args);
$what = "generated CA request for";
}
else
{
$self->{openssl}->cmd('req',"-x509 $common_args -new -out $cacert",$args);
$what = "initialized self-signed";
}
$self->warn("Successfully $what CA $self->{name}")
if $args->{verbose};
}
}
sub checkCA
{
my $self = shift;
my $dir = $self->caDir();
$self->die("Uninitialized CA: missing or unreadable ca certificate in $dir")
unless -r "$dir/ca.crt";
$self->die("Uninitialized CA: missing or unreadable ca private key in $dir")
unless -r "$dir/private/ca.key";
$dir;
}
. . .
And towards the end of the script file this:
. . .
$self->{csp} = $csp;
$cmd = '' if $cmd eq 'dummy';
my $engine = "-engine opensc" if $ENV{CSP_OPENSC};
my $redirect = ($args->{verbose} == 0 && $rw ne 'r' ? ">/dev/null 2>&1" : "");
warn "${lp}$self->{openssl} $cmd $cfgcmd $cmdline ${redirect}${rp}"
if $ENV{CSPDEBUG};
if ($rw eq 's')
{
$self->{rc} = system("$self->{openssl} $cmd $engine $cfgcmd $cmdline ${redirect}");
}
else
{
open $self->{fh},"${lp}$self->{openssl} $cmd $engine $cfgcmd $cmdline ${redirect}${rp}" or
$self->{csp}->die("Unable to execute: $!");
}
$self;
}
. . .
When I run this using the following command line with debugging on:
csp HLL_ROOT init \
--keysize=4096 \
--days=7318 \
--url=ca.harte-lyne.ca \
--email=certificates@harte-lyne.ca \
--digest=sha512 \
--verbose \
"CN=HLL_ROOT,OU=Networked Data Services,O=Harte & Lyne Limited,L=Hamilton,ST=Ontario,C=CA,DC=harte-lyne,DC=ca"
Then I see this:
openssl genrsa -des3 -passout pass:'a test' -out /home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT/private/ca.key 4096
followed by:
openssl genrsa -des3 -passout pass:'a test' -out /home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT/private/ca.key 4096
and ending with:
[CSP][HLL_ROOT] Successfully initialized self-signed CA HLL_ROOT
However, the expected outputs of ca.key and ca.crt are not found in the directories shown as arguments in the commands above.
$ find /home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT -name ca\.\*
$
Yet, if I copy and paste those exact commands into my bash session shell they work.
openssl genrsa -des3 -passout pass:'a test' -out /home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT/private/ca.key 4096
Generating RSA private key, 4096 bit long modulus
.....................................++
........................++
e is 65537 (0x10001)
and
openssl req -config /home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT/tmp/csp-8154.conf -x509 -sha512 -days 7318 -key /home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT/private/ca.key -passin pass:'a test' -new -out /home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT/ca.crt
yields:
$ find /home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT -name ca\.\*
/home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT/private/ca.key
/home/byrnejb/Projects/Software/rcsp/ca_test_a/csp/HLL_ROOT/ca.crt
That seems to me that the commands are being created properly but that the openssl utility is not being called. As there is no branching code in the section where these commands are generated I conclude that the construct $self->{openssl}->cmd('req',"-x509 $common_args -new -out $cacert",$args);
is the actual call to openssl but I do not know how this is meant to work.
How is this supposed to work? Why is it not working?
And should not the return code from openssl be checked?
回答1:
Per @simbabque comment the place that the openssl call is made is here:
1398 use IPC::Run qw( start pump finish timeout new_appender new_chunker);
. . .
1418 sub cmd
1419 {
1420 my $self = shift;
1421 my $cmd = shift;
1422 my $cmdline = shift;
1423 my $args = shift;
1424
1425 my $conf;
1426 my $cfgcmd;
. . .
1448 $self->{_handle}->pump while length ${$self->{_in}};
. . .
The underlying difficulty is the use of embedded white-space in the pass-phrase. As written the code passes arguments to IPC:Run
as a concatenated string. For arguments passed as a string IPC:Run uses white-space as an argument delimiter. The correct method of dealing with this is to refactor the code to use an array to pass arguments instead.
回答2:
I'm the original author of that package and I abandoned it long ago for reasons that should be apparent. Go take a look at https://github.com/leifj/ici for something a bit more maintainable (even tho its just basically bash-scripts)
来源:https://stackoverflow.com/questions/40162613/how-and-where-is-openssl-called-in-this-script