Skip to content

Commit

Permalink
Add parent to CA to for chain storage + make final
Browse files Browse the repository at this point in the history
Make CAResolverImp and CA model final, this shouldn't be extended
but a custom implementation should be used instead.

Storing the CA directly isn't possible, and so it should be transformed
to an application level entity instead.
  • Loading branch information
sstok committed Feb 3, 2024
1 parent ad2ed5e commit 662dc7c
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 15 deletions.
12 changes: 5 additions & 7 deletions src/CA.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@

namespace Rollerworks\Component\X509Validator;

class CA
final readonly class CA
{
public function __construct(private readonly string $contents) {}

public function getContents(): string
{
return $this->contents;
}
public function __construct(
public string $contents,
public ?self $parent = null
) {}
}
10 changes: 6 additions & 4 deletions src/CAResolverImpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Rollerworks\Component\X509Validator\Violation\TooManyCAsProvided;
use Rollerworks\Component\X509Validator\Violation\UnableToResolveParent;

class CAResolverImpl implements CAResolver
final class CAResolverImpl implements CAResolver
{
private readonly X509DataExtractor $extractor;

Expand Down Expand Up @@ -64,6 +64,8 @@ private function isSignatureValid(string $contents, string $pupKey): bool
/** @param array<string, string> $caList */
private function resolveCA(string $certificate, array $caList): CA
{
$parent = null;

foreach ($caList as $index => $contents) {
$data = $this->extractor->extractRawData($contents, $index, true);
$this->validateCA($data);
Expand All @@ -72,16 +74,16 @@ private function resolveCA(string $certificate, array $caList): CA
continue;
}

// Check if self signed, otherwise resolve it's parent
// Check if the CA is self signed, otherwise resolve it's parent
if (! $this->isSignatureValid($contents, $data->pubKey)) {
// THIS issuer cannot be the parent of another parent, so remove it
// from the list. This speeds-up the resolving process.
unset($caList[$index]);

$this->resolveCA($contents, $caList);
$parent = $this->resolveCA($contents, $caList);
}

return new CA($contents);
return new CA($contents, $parent);
}

$x509Info = $this->extractor->extractRawData($certificate);
Expand Down
2 changes: 1 addition & 1 deletion src/OCSPValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public function validateStatus(string $certificate, array $caList = []): void
}

$certificateSeq = $this->certificateLoader->fromString($certificate);
$issuerCertificate = $this->certificateLoader->fromString($ca->getContents());
$issuerCertificate = $this->certificateLoader->fromString($ca->contents);

$ocspResponderUrl = $this->certificateInfo->extractOcspResponderUrl($certificateSeq);

Expand Down
7 changes: 5 additions & 2 deletions src/Violation/UnableToResolveParent.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@

final class UnableToResolveParent extends Violation
{
public function __construct(private readonly string $name, private readonly string $issuer, int $code = 1)
{
public function __construct(
public readonly string $name,
public readonly string $issuer,
int $code = 1
) {
parent::__construct(sprintf('Unable to resolve the parent CA of certificate "%s", issued by "%s".', $name, $issuer), $code);
}

Expand Down
3 changes: 2 additions & 1 deletion tests/CAResolverImplTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Rollerworks\Component\X509Validator\Violation\TooManyCAsProvided;
use Rollerworks\Component\X509Validator\Violation\UnableToResolveParent;
use Rollerworks\Component\X509Validator\Violation\UnprocessablePEM;
use Rollerworks\Component\X509Validator\X509Info;

/**
* @internal
Expand Down Expand Up @@ -501,7 +502,7 @@ public function it_resolves_a_valid_ca_list(): void
'DigiCert SHA2 Secure Server CA' => $ca1,
]);

$intermediateCA = new CA($ca1);
$intermediateCA = new CA($ca1, new CA($ca2));

self::assertEquals($intermediateCA, $ca);
}
Expand Down

0 comments on commit 662dc7c

Please sign in to comment.