• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LibreSign / libresign / 19654064764

25 Nov 2025 12:34AM UTC coverage: 40.307%. First build
19654064764

Pull #5770

github

web-flow
Merge 83a1aadc8 into 328da9e69
Pull Request #5770: feat: validate crl

143 of 220 new or added lines in 8 files covered. (65.0%)

4755 of 11797 relevant lines covered (40.31%)

3.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.08
/lib/Handler/CfsslServerHandler.php
1
<?php
2

3
declare(strict_types=1);
4
/**
5
 * SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8

9
namespace OCA\Libresign\Handler;
10

11
use Closure;
12
use OCA\Libresign\Exception\LibresignException;
13
use OCA\Libresign\Service\CertificatePolicyService;
14

15
class CfsslServerHandler {
16
        private string $csrServerFile = '';
17
        private string $configServerFile = '';
18
        private string $configServerFileHash = '';
19
        private string $crlUrl = '';
20
        private Closure $getCurrentConfigPath;
21

22
        public function __construct(
23
                private CertificatePolicyService $certificatePolicyService,
24
        ) {
25
        }
56✔
26

27
        /**
28
         * Create a callback to get config path not at the constructor because
29
         * getting at constructor, every time that the class is instantiated, will
30
         * try to create the config path if not exists.
31
         */
32
        public function configCallback(Closure $callback): void {
33
                $this->getCurrentConfigPath = $callback;
56✔
34
                $this->getCurrentConfigPath = function () use ($callback): void {
56✔
35
                        if ($this->csrServerFile) {
×
36
                                return;
×
37
                        }
38
                        $configPath = $callback();
×
39
                        $this->csrServerFile = $configPath . DIRECTORY_SEPARATOR . 'csr_server.json';
×
40
                        $this->configServerFile = $configPath . DIRECTORY_SEPARATOR . 'config_server.json';
×
41
                        $this->configServerFileHash = $configPath . DIRECTORY_SEPARATOR . 'hashes.sha256';
×
42
                };
56✔
43
        }
44

45
        public function createConfigServer(
46
                string $commonName,
47
                array $names,
48
                int $expirityInDays,
49
                string $crlUrl = '',
50
        ): void {
NEW
51
                $this->crlUrl = $crlUrl;
×
52
                $this->putCsrServer(
×
53
                        $commonName,
×
54
                        $names,
×
55
                        $expirityInDays,
×
56
                        $crlUrl,
×
57
                );
×
58
                $this->saveNewConfig($expirityInDays);
×
59
        }
60

61
        private function putCsrServer(
62
                string $commonName,
63
                array $names,
64
                int $expirityInDays,
65
                string $crlUrl,
66
        ): void {
67
                $content = [
×
68
                        'CN' => $commonName,
×
69
                        'key' => [
×
70
                                'algo' => 'rsa',
×
71
                                'size' => 2048,
×
72
                        ],
×
73
                        'ca' => [
×
74
                                'expiry' => ($expirityInDays * 24) . 'h',
×
75
                                /**
76
                                 * Look the RFC about pathlen constraint
77
                                 *
78
                                 * @link https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.9
79
                                 */
80
                                'pathlen' => 1,
×
81
                        ],
×
82
                        'names' => [],
×
83
                ];
×
84
                if (!empty($crlUrl)) {
×
85
                        $content['crl_url'] = $crlUrl;
×
86
                }
87
                foreach ($names as $id => $name) {
×
88
                        $content['names'][0][$id] = is_array($name['value']) ? implode(', ', $name['value']) : $name['value'];
×
89
                }
90
                ($this->getCurrentConfigPath)();
×
91
                $response = file_put_contents($this->csrServerFile, json_encode($content));
×
92
                if ($response === false) {
×
93
                        throw new LibresignException(
×
94
                                "Error while writing CSR server file.\n"
×
95
                                . 'Remove the CFSSL API URI and Config path to use the default values.',
×
96
                                500
×
97
                        );
×
98
                }
99
        }
100
        private function saveNewConfig(int $expirity): void {
101
                $config = [
×
102
                        'signing' => [
×
103
                                'profiles' => [
×
104
                                        'client' => [
×
105
                                                'expiry' => ($expirity * 24) . 'h',
×
106
                                                'usages' => [
×
107
                                                        'signing',
×
108
                                                        'digital signature',
×
109
                                                        'content commitment',
×
110
                                                        'key encipherment',
×
111
                                                        'client auth',
×
112
                                                        'email protection'
×
113
                                                ],
×
114
                                                'ca_constraint' => [
×
115
                                                        'is_ca' => false
×
116
                                                ],
×
117
                                        ],
×
118
                                ],
×
119
                        ],
×
120
                ];
×
121

NEW
122
                if (!empty($this->crlUrl)) {
×
NEW
123
                        $config['signing']['profiles']['client']['crl_url'] = $this->crlUrl;
×
124
                }
125

126
                $oid = $this->certificatePolicyService->getOid();
×
127
                $cps = $this->certificatePolicyService->getCps();
×
128
                if ($oid && $cps) {
×
129
                        $config['signing']['profiles']['client']['policies'][] = [
×
130
                                'id' => $oid,
×
131
                                'qualifiers' => [
×
132
                                        [
×
133
                                                'type' => 'id-qt-cps',
×
134
                                                'value' => $cps,
×
135
                                        ],
×
136
                                ],
×
137
                        ];
×
138
                }
139
                $this->saveConfig($config);
×
140
        }
141

142
        private function saveConfig(array $config): void {
143
                $jsonConfig = json_encode($config);
×
144
                ($this->getCurrentConfigPath)();
×
145
                $response = file_put_contents($this->configServerFile, $jsonConfig);
×
146
                if ($response === false) {
×
147
                        throw new LibresignException('Error while writing config server file!', 500);
×
148
                }
149
                $hash = hash('sha256', $jsonConfig) . ' config_server.json';
×
150
                file_put_contents($this->configServerFileHash, $hash);
×
151
        }
152

153
        public function updateExpirity(int $expirity): void {
154
                ($this->getCurrentConfigPath)();
×
155
                if (file_exists($this->configServerFileHash)) {
×
156
                        $hashes = file_get_contents($this->configServerFileHash);
×
157
                        preg_match('/(?<hash>\w*) +config_server.json/', $hashes, $matches);
×
158
                        $savedHash = $matches['hash'];
×
159
                } else {
160
                        $savedHash = '';
×
161
                }
162
                $jsonConfig = file_get_contents($this->configServerFile);
×
163
                $currentHash = hash('sha256', $jsonConfig);
×
164
                if ($currentHash === $savedHash) {
×
165
                        return;
×
166
                }
167
                $config = json_decode($jsonConfig, true);
×
168
                $config['signing']['profiles']['CA']['expiry'] = ($expirity * 24) . 'h';
×
169
                $config['signing']['profiles']['client']['expiry'] = ($expirity * 24) . 'h';
×
170
                $this->saveConfig($config);
×
171
        }
172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc