Crypt-LE
view release on metacpan or search on metacpan
script/le.pl view on Meta::CPAN
if ($issuer) {
my $target_pfx = $opt->{'crt'};
$target_pfx=~s/\.[^\.]*$//;
$opt->{'logger'}->info("Exporting certificate to $target_pfx.pfx.");
return $opt->{'error'}->("Error exporting pfx: " . $le->error_details, 'CERTIFICATE_EXPORT') if $le->export_pfx("$target_pfx.pfx", $opt->{'export-pfx'}, $certificate, $le->csr_key, $issuer, $opt->{'tag-pfx'});
} else {
return $opt->{'error'}->("Issuer's certificate is not available, skipping pfx export to avoid creating an invalid pfx.", 'CERTIFICATE_EXPORT_ISSUER');
}
}
if ($opt->{'complete-handler'}) {
my $data = {
# Note, certificate here is just a domain certificate, issuer is passed separately - so handler could merge those or use them separately as well.
certificate => $le->certificate, certificate_file => $opt->{'crt'}, key_file => $opt->{'csr-key'}, issuer => $le->issuer, alternatives => $le->alternative_certificates(),
domains => $le->domains, logger => $opt->{'logger'},
};
my $rv;
eval {
$rv = $opt->{'complete-handler'}->complete($data, \%callback_data);
};
if ($@ or !$rv) {
return $opt->{'error'}->("Completion handler " . ($@ ? "thrown an error: $@" : "did not return a true value"), 'COMPLETION_HANDLER');
}
}
$opt->{'logger'}->info("===> NOTE: You have been using the test server for this certificate. To issue a valid trusted certificate add --live option.") unless $opt->{'live'};
$opt->{'logger'}->info("The job is done, enjoy your certificate!\n");
return { code => $opt->{'issue-code'}||0 };
}
sub parse_options {
my $opt = shift;
my $args = @ARGV;
GetOptions ($opt, 'key=s', 'csr=s', 'csr-key=s', 'domains=s', 'path=s', 'crt=s', 'email=s', 'curve=s', 'server=s', 'directory=s', 'api=i', 'config=s', 'renew=i', 'renew-check=s','issue-code=i',
'handle-with=s', 'handle-as=s', 'handle-params=s', 'complete-with=s', 'complete-params=s', 'log-config=s', 'update-contacts=s', 'export-pfx=s', 'tag-pfx=s',
'eab-kid=s', 'eab-hmac-key=s', 'ca=s', 'alternative=i', 'generate-missing', 'generate-only', 'revoke', 'legacy', 'unlink', 'delayed', 'live', 'quiet', 'debug+', 'help') ||
return $opt->{'error'}->("Use --help to see the usage examples.", 'PARAMETERS_PARSE');
if ($opt->{'config'}) {
return $opt->{'error'}->("Configuration file '$opt->{'config'}' is not readable", 'PARAMETERS_PARSE') unless -r $opt->{'config'};
my $rv = parse_config($opt);
return $opt->{'error'}->("Configuration file error: $rv" , 'PARAMETERS_PARSE') if $rv;
}
usage_and_exit($opt) unless ($args and !$opt->{'help'});
my $rv = reconfigure_log($opt);
return $rv if $rv;
$opt->{'logger'}->info("[ Crypt::LE client v$VERSION started. ]");
my $custom_server;
return $opt->{'error'}->("Please use either 'server' or 'directory', but not both.", 'PARAMETERS_CONFLICT') if ($opt->{'server'} and $opt->{'directory'});
if ($opt->{'eab-kid'} or $opt->{'eab-hmac-key'}) {
return $opt->{'error'}->("Please specify both eab-kid and eab-hmac-key.", 'PARAMETERS_CONFLICT') unless ($opt->{'eab-kid'} and $opt->{'eab-hmac-key'});
}
foreach my $url_type (qw<server directory>) {
if ($opt->{$url_type}) {
return $opt->{'error'}->("Unsupported protocol for the custom $url_type URL: $1.", 'CUSTOM_' . uc($url_type) . '_URL') if ($opt->{$url_type}=~s~^(.*?)://~~ and uc($1) ne 'HTTPS');
my $server = $opt->{$url_type}; # For logging.
$opt->{'logger'}->warn("Remember to URL-escape special characters if you are using $url_type URL with basic auth credentials.") if $server=~s~[^@/]*@~~;
$opt->{'logger'}->info("Custom $url_type URL 'https://$server' is used.");
$custom_server = 1;
}
}
if ($custom_server) {
return $opt->{'error'}->("Please do not use 'ca' when the custom server is set explicitly.", 'PARAMETERS_CONFLICT') if $opt->{'ca'};
# Ignore options which do not make sense if the custom server/directory is specified.
if ($opt->{'live'}) {
$opt->{'logger'}->warn("Note: 'live' option is ignored when the custom server/directory is set.");
undef $opt->{'live'};
}
}
if ($opt->{'renew-check'}) {
$opt->{'error'}->("Unsupported protocol for the renew check URL: $1.", 'RENEW_CHECK_URL') if ($opt->{'renew-check'}=~s~^(.*?)://~~ and uc($1) ne 'HTTPS');
}
return $opt->{'error'}->("Incorrect parameters - need account key file name specified.", 'ACCOUNT_KEY_FILENAME_REQUIRED') unless $opt->{'key'};
if (-e $opt->{'key'}) {
return $opt->{'error'}->("Account key file is not readable.", 'ACCOUNT_KEY_NOT_READABLE') unless (-r $opt->{'key'});
} else {
return $opt->{'error'}->("Account key file is missing and the option to generate missing files is not used.", 'ACCOUNT_KEY_MISSING') unless $opt->{'generate-missing'};
}
unless ($opt->{'crt'} or $opt->{'generate-only'} or $opt->{'update-contacts'}) {
return $opt->{'error'}->("Please specify a file name for the certificate.", 'CERTIFICATE_FILENAME_REQUIRED');
}
if ($opt->{'export-pfx'}) {
if ($opt->{'crt'} and $opt->{'crt'}=~/\.pfx$/i) {
return $opt->{'error'}->("Please ensure that the extension of the certificate filename is different from '.pfx' to be able to additionally export the certificate in pfx form.", 'CERTIFICATE_BAD_FILENAME_EXTENSION');
}
unless ($opt->{'csr-key'} and (-r $opt->{'csr-key'} or ($opt->{'generate-missing'} and ! -e $opt->{'csr'}))) {
return $opt->{'error'}->("Need either existing csr-key specified or having CSR file generated (via 'generate-missing') for PFX export to work", 'NEED_CSR_KEY_FOR_EXPORT');
}
} elsif ($opt->{'tag-pfx'}) {
$opt->{'logger'}->warn("Option 'tag-pfx' makes no sense without 'export-pfx' - ignoring.");
}
if ($opt->{'revoke'}) {
return $opt->{'error'}->("Need a certificate file for revoke to work.", 'NEED_CERTIFICATE_FOR_REVOKE') unless ($opt->{'crt'} and -r $opt->{'crt'});
return $opt->{'error'}->("Need an account key - revoke assumes you had a registered account when got the certificate.", 'NEED_ACCOUNT_KEY_FOR_REVOKE') unless (-r $opt->{'key'});
} elsif (!$opt->{'update-contacts'}) {
return $opt->{'error'}->("Incorrect parameters - need CSR file name specified.", 'CSR_FILENAME_REQUIRED') unless $opt->{'csr'};
if (-e $opt->{'csr'}) {
return $opt->{'error'}->("CSR file is not readable.", 'CSR_NOT_READABLE') unless (-r $opt->{'csr'});
} else {
return $opt->{'error'}->("CSR file is missing and the option to generate missing files is not used.", 'CSR_MISSING') unless $opt->{'generate-missing'};
return $opt->{'error'}->("CSR file is missing and CSR-key file name is not specified.", 'CSR_MISSING') unless $opt->{'csr-key'};
return $opt->{'error'}->("Domain list should be provided to generate a CSR.", 'DOMAINS_REQUIRED') unless ($opt->{'domains'} and $opt->{'domains'}!~/^[\s\,]*$/);
}
if ($opt->{'path'}) {
my @non_writable = ();
foreach my $path (grep { $_ } split /\s*,\s*/, $opt->{'path'}) {
push @non_writable, $path unless (-d $path and -w _);
}
return $opt->{'error'}->("Path to save challenge files into should be a writable directory for: " . join(', ', @non_writable), 'CHALLENGE_DIRECTORY_NOT_WRITABLE') if @non_writable;
} elsif ($opt->{'unlink'}) {
( run in 0.656 second using v1.01-cache-2.11-cpan-39bf76dae61 )