Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.31% covered (success)
92.31%
24 / 26
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CertificateChainService
92.31% covered (success)
92.31%
24 / 26
66.67% covered (warning)
66.67%
2 / 3
10.05
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCertificateChain
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
5
 getSha256FromResource
77.78% covered (warning)
77.78%
7 / 9
0.00% covered (danger)
0.00%
0 / 1
4.18
1<?php
2
3declare(strict_types=1);
4
5/**
6 * SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
7 * SPDX-License-Identifier: AGPL-3.0-or-later
8 */
9
10namespace OCA\Libresign\Service\File;
11
12use OCA\Libresign\Db\File;
13use OCA\Libresign\Handler\SignEngine\Pkcs12Handler;
14use Psr\Log\LoggerInterface;
15
16class CertificateChainService {
17    public function __construct(
18        private Pkcs12Handler $pkcs12Handler,
19        private LoggerInterface $logger,
20    ) {
21    }
22
23    public function getCertificateChain($fileNode, File $libreSignFile, $options): array {
24        if (!$options->isValidateFile() || !$libreSignFile->getSignedNodeId()) {
25            return [];
26        }
27
28        try {
29            $resource = $fileNode->fopen('rb');
30            if (!is_resource($resource)) {
31                $this->logger->warning('Failed to load certificate chain: unable to open signed file stream');
32                return [];
33            }
34            $sha256 = $this->getSha256FromResource($resource);
35            rewind($resource);
36            $this->pkcs12Handler->setIsLibreSignFile($sha256 === $libreSignFile->getSignedHash());
37            $this->pkcs12Handler->setPolicyUserIdForValidation($libreSignFile->getUserId());
38            $certData = $this->pkcs12Handler->getCertificateChain($resource);
39            fclose($resource);
40            return $certData;
41        } catch (\Exception $e) {
42            $this->logger->warning('Failed to load certificate chain: ' . $e->getMessage());
43            return [];
44        }
45    }
46
47    private function getSha256FromResource($resource): string {
48        if (!is_resource($resource)) {
49            return '';
50        }
51
52        $hashContext = hash_init('sha256');
53        while (!feof($resource)) {
54            $buffer = fread($resource, 8192);
55            if ($buffer === false) {
56                break;
57            }
58            hash_update($hashContext, $buffer);
59        }
60        return hash_final($hashContext);
61    }
62}