App-CamelPKI

 view release on metacpan or  search on metacpan

lib/App/CamelPKI/CA.pm  view on Meta::CPAN


sub certificate {
    my ($self) = @_;
    $self->{certificate} ||= App::CamelPKI::Certificate->load
        ($self->_certificate_path);
}

=head2 issue($certtemplate, $pubkey, $key1 => $val1, ...)

Issue on to many new certificates. $pubkey is a public key, in the
form of an L<App::CamelPKI::PublicKey> object. $certtemplate is the name
of a subclass of L<App::CamelPKI::CertTemplate>; $key1 => $val1, ... are
nominatives parameters to pass to $certtemplate for him to generate
associated certificates (see details in 
L<App::CamelPKI::CertTemplate/prepare_certificate> and
L<App::CamelPKI::CertTemplate/list_keys>).

Internally, I<sign> control arguments, and the calls

  $certtemplate->test_certificate_conflict($db, $key1 => $val1, ...)

to verify if the certificate to create is compliant to the existing
certificates. If it's ok, I<sign> invokes

  $certtemplate->prepare_certificate($cacert, $newcert, $key1 => $val1, ...)

At last, I<sign> fix the serial number, conforming to the current CA status,
and records the certificate in database. The certificate may then be retrieved
using L</commit>.

=cut

sub issue {
    my ($self, $template, $pubkey, @opts) = @_;

    # Note the explicit class call: so the template has no authority
    # to overload this method at will.
    my %dbopts = $template->App::CamelPKI::CertTemplate::normalize_opts(@opts);
    delete $dbopts{time}; # Sémantique réservée
    $dbopts{template} = $template;
    my %templateopts = %dbopts;
    $templateopts{time} = App::CamelPKI::Time->now->zulu;

    foreach my $conflictcert
        ($template->test_certificate_conflict
         ($self->database_facet($template), %templateopts)) {
        # FIXME: should be more flexible (refuse the operation
        # instead of revoking conflicting certificates, or give the
        # "superseded" reason in the CRL...)
        $self->revoke($template, $conflictcert) unless
            grep {$conflictcert->equals($_->{cert})} @{$self->{signed}};
    }

    my $cert = Crypt::OpenSSL::CA::X509->new
        ($pubkey->as_crypt_openssl_ca_publickey);
    $template->prepare_certificate
        ($self->certificate, $cert, %templateopts);
    $cert->set_serial(sprintf("0x%x",
                              $self->{db}->next_serial("certificate")));
    $cert = App::CamelPKI::Certificate->parse
        ($cert->sign($self->_private_key,
                     $template->signature_hash));
    push @{$self->{signed}}, { cert => $cert, opts => \%dbopts };
    return;
}

=head2 revoke($certtemplate, $certificate, %options)

Marks $certificate, an object of the L<App::CamelPKI::Certificate> class,
which has been certified via the $certtemplate template, as revoked.
It's prohibited to revoke a certificate that has just been certified
in the current transaction (see L</Coherence>); If this situation
is detected, triggers an exception. In the same way, the template
may cause additional revocations following the revocation of
 $certificate (see L<App::CamelPKI::CertTemplate/test_cascaded_revocation>).

This method is delegated to L<App::CamelPKI::CADB/revoke>, and recognized named
options are documented at this section.

=cut

sub revoke {
    throw App::CamelPKI::Error::Internal("WRONG_NUMBER_ARGS")
        unless (@_ % 2);
    my ($self, $template, $cert, %options) = @_;
    throw App::CamelPKI::Error::Internal("INCORRECT_ARGS")
        if (! defined $cert);

    throw App::CamelPKI::Error::Privilege
        ("Attempt to revoke a certificate foreign to this template",
         -certificate => $cert,
         -template => $template)
            unless $self->database_facet($template)
                ->search(-certificate => $cert,
                         -revoked => undef)->count;
    $self->{db}->revoke($cert, %options);
}

=head2 commit()

Records all writes in database, and returns the certificate list issued
with L</sign> scince the creation of the object or scince the previous
call to I<commit>. Certificates are returned in the form of a list of
L<App::CamelPKI::Certificate> objects, in the same order as the corresponding
call to L</sign>.

=cut

sub commit {
    my ($self) = @_;

    my @signed = @{delete($self->{signed}) || []};

    my $checks = {};
    push @{$checks->{$_->{opts}->{template}}}, $_ foreach @signed;
    $_->test_issued_certs_coherent(@{$checks->{$_}}) foreach
        (keys %$checks);

    my @retval;
    foreach my $signed (@signed) {
        $self->{db}->add($signed->{cert}, %{$signed->{opts}});

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 0.498 second using v1.00-cache-2.02-grep-82fe00e-cpan-dad7e4baca0 )