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 )