Skip to content

Commit 804a6d8

Browse files
committed
Enhance certificate verification process
1 parent 8a70272 commit 804a6d8

File tree

1 file changed

+29
-35
lines changed

1 file changed

+29
-35
lines changed

library/X509/CertificateUtils.php

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use Icinga\Application\Logger;
99
use Icinga\File\Storage\TemporaryLocalFileStorage;
1010
use Icinga\Module\X509\Model\X509Certificate;
11-
use Icinga\Module\X509\Model\X509CertificateChain;
1211
use Icinga\Module\X509\Model\X509CertificateSubjectAltName;
1312
use Icinga\Module\X509\Model\X509Dn;
1413
use Icinga\Module\X509\Model\X509Target;
@@ -18,6 +17,8 @@
1817
use ipl\Stdlib\Filter;
1918
use ipl\Stdlib\Str;
2019

20+
use function ipl\Stdlib\yield_groups;
21+
2122
class CertificateUtils
2223
{
2324
/**
@@ -453,52 +454,39 @@ public static function verifyCertificates(Connection $db)
453454
$files->create($caFile, implode("\n", $contents));
454455

455456
$count = 0;
457+
$certs = X509Certificate::on($db)
458+
->with(['chain'])
459+
->utilize('chain.target')
460+
->columns(['chain.id', 'certificate'])
461+
->filter(Filter::equal('chain.valid', false))
462+
->orderBy('chain.id')
463+
->orderBy(new Expression('certificate_link.order'), SORT_DESC);
456464

457465
$db->beginTransaction();
458466

459467
try {
460-
$chains = X509CertificateChain::on($db)->utilize('target');
461-
$chains
462-
->columns(['id'])
463-
->filter(Filter::equal('valid', false));
464-
465-
foreach ($chains as $chain) {
466-
++$count;
467-
468-
$certs = X509Certificate::on($db)->utilize('chain');
469-
$certs
470-
->columns(['certificate'])
471-
->filter(Filter::equal('chain.id', $chain->id))
472-
->getSelectBase()
473-
->orderBy('certificate_link.order', 'DESC');
474-
475-
$collection = [];
476-
477-
foreach ($certs as $cert) {
478-
$collection[] = $cert->certificate;
479-
}
480-
468+
$caFile = escapeshellarg($files->resolvePath($caFile));
469+
$verifyCertsFunc = function (int $chainId, array $collection) use ($db, $caFile) {
470+
$certFiles = new TemporaryLocalFileStorage();
481471
$certFile = uniqid('cert');
482-
483-
$files->create($certFile, array_pop($collection));
472+
$certFiles->create($certFile, array_pop($collection));
484473

485474
$untrusted = '';
486-
487475
if (! empty($collection)) {
488476
$intermediateFile = uniqid('intermediate');
489-
$files->create($intermediateFile, implode("\n", $collection));
477+
$certFiles->create($intermediateFile, implode("\n", $collection));
490478

491479
$untrusted = sprintf(
492480
' -untrusted %s',
493-
escapeshellarg($files->resolvePath($intermediateFile))
481+
escapeshellarg($certFiles->resolvePath($intermediateFile))
494482
);
495483
}
496484

497485
$command = sprintf(
498486
'openssl verify -CAfile %s%s %s 2>&1',
499-
escapeshellarg($files->resolvePath($caFile)),
487+
$caFile,
500488
$untrusted,
501-
escapeshellarg($files->resolvePath($certFile))
489+
escapeshellarg($certFiles->resolvePath($certFile))
502490
);
503491

504492
$output = null;
@@ -513,18 +501,24 @@ public static function verifyCertificates(Connection $db)
513501

514502
preg_match('/^error \d+ at \d+ depth lookup:(.+)$/m', $output, $match);
515503

516-
if (!empty($match)) {
504+
if (! empty($match)) {
517505
$set = ['invalid_reason' => trim($match[1])];
518506
} else {
519507
$set = ['valid' => 'y', 'invalid_reason' => null];
520508
}
521509

522510
// TODO: https://github.com/Icinga/ipl-orm/pull/78
523-
$db->update(
524-
'x509_certificate_chain',
525-
$set,
526-
['id = ?' => $chain->id]
527-
);
511+
$db->update('x509_certificate_chain', $set, ['id = ?' => $chainId]);
512+
};
513+
514+
$groupBy = function (X509Certificate $cert): array {
515+
// Group all the certificates by their chain id.
516+
return [$cert->chain->id, $cert->certificate];
517+
};
518+
519+
foreach (yield_groups($certs, $groupBy) as $chainId => $collection) {
520+
++$count;
521+
$verifyCertsFunc($chainId, $collection);
528522
}
529523

530524
$db->commitTransaction();

0 commit comments

Comments
 (0)