Skip to content

Commit 90d7d9e

Browse files
committed
fix: add pending code after apply cherry-pick
Reference: #5626 Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent f97c787 commit 90d7d9e

File tree

4 files changed

+204
-46
lines changed

4 files changed

+204
-46
lines changed

lib/Handler/CertificateEngine/AEngineHandler.php

Lines changed: 136 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -325,20 +325,14 @@ public function getUID(): string {
325325
return str_replace(' ', '+', $this->UID);
326326
}
327327

328-
public function expirity(): int {
329-
$expirity = $this->appConfig->getValueInt(Application::APP_ID, 'expiry_in_days', 365);
330-
if ($expirity < 0) {
331-
return 365;
332-
}
333-
return $expirity;
334-
}
335-
336-
public function isSetupOk(): bool {
337-
return strlen($this->appConfig->getValueString(Application::APP_ID, 'authkey', '')) > 0;
328+
public function getLeafExpiryInDays(): int {
329+
$exp = $this->appConfig->getValueInt(Application::APP_ID, 'expiry_in_days', 365);
330+
return $exp > 0 ? $exp : 365;
338331
}
339332

340-
public function configureCheck(): array {
341-
throw new \Exception('Necessary to implement configureCheck method');
333+
public function getCaExpiryInDays(): int {
334+
$exp = $this->appConfig->getValueInt(Application::APP_ID, 'ca_expiry_in_days', 3650); // 10 years
335+
return $exp > 0 ? $exp : 3650;
342336
}
343337

344338
private function getCertificatePolicy(): array {
@@ -354,6 +348,136 @@ private function getCertificatePolicy(): array {
354348
return $return;
355349
}
356350

351+
abstract protected function getConfigureCheckResourceName(): string;
352+
353+
abstract protected function getCertificateRegenerationTip(): string;
354+
355+
abstract protected function getEngineSpecificChecks(): array;
356+
357+
abstract protected function getSetupSuccessMessage(): string;
358+
359+
abstract protected function getSetupErrorMessage(): string;
360+
361+
abstract protected function getSetupErrorTip(): string;
362+
363+
public function configureCheck(): array {
364+
$checks = $this->getEngineSpecificChecks();
365+
366+
if (!$this->isSetupOk()) {
367+
return array_merge($checks, [
368+
(new ConfigureCheckHelper())
369+
->setErrorMessage($this->getSetupErrorMessage())
370+
->setResource($this->getConfigureCheckResourceName())
371+
->setTip($this->getSetupErrorTip())
372+
]);
373+
}
374+
375+
$checks[] = (new ConfigureCheckHelper())
376+
->setSuccessMessage($this->getSetupSuccessMessage())
377+
->setResource($this->getConfigureCheckResourceName());
378+
379+
$modernFeaturesCheck = $this->checkRootCertificateModernFeatures();
380+
if ($modernFeaturesCheck) {
381+
$checks[] = $modernFeaturesCheck;
382+
}
383+
384+
return $checks;
385+
}
386+
387+
protected function checkRootCertificateModernFeatures(): ?ConfigureCheckHelper {
388+
$configPath = $this->getConfigPath();
389+
$caCertPath = $configPath . DIRECTORY_SEPARATOR . 'ca.pem';
390+
391+
try {
392+
$certContent = file_get_contents($caCertPath);
393+
if (!$certContent) {
394+
return (new ConfigureCheckHelper())
395+
->setErrorMessage('Failed to read root certificate file')
396+
->setResource($this->getConfigureCheckResourceName())
397+
->setTip('Check file permissions and disk space');
398+
}
399+
400+
$x509Resource = openssl_x509_read($certContent);
401+
if (!$x509Resource) {
402+
return (new ConfigureCheckHelper())
403+
->setErrorMessage('Failed to parse root certificate')
404+
->setResource($this->getConfigureCheckResourceName())
405+
->setTip('Root certificate file may be corrupted or invalid');
406+
}
407+
408+
$parsed = openssl_x509_parse($x509Resource);
409+
if (!$parsed) {
410+
return (new ConfigureCheckHelper())
411+
->setErrorMessage('Failed to extract root certificate information')
412+
->setResource($this->getConfigureCheckResourceName())
413+
->setTip('Root certificate may be in an unsupported format');
414+
}
415+
416+
$criticalIssues = [];
417+
$minorIssues = [];
418+
419+
if (isset($parsed['serialNumber'])) {
420+
$serialNumber = $parsed['serialNumber'];
421+
$serialDecimal = hexdec($serialNumber);
422+
if ($serialDecimal <= 1) {
423+
$minorIssues[] = 'Serial number is simple (zero or one)';
424+
}
425+
} else {
426+
$criticalIssues[] = 'Serial number is missing';
427+
}
428+
429+
$missingExtensions = [];
430+
if (!isset($parsed['extensions']['subjectKeyIdentifier'])) {
431+
$missingExtensions[] = 'Subject Key Identifier (SKI)';
432+
}
433+
434+
$isSelfSigned = (isset($parsed['issuer']) && isset($parsed['subject'])
435+
&& $parsed['issuer'] === $parsed['subject']);
436+
437+
/**
438+
* @todo workarround for missing AKI at certificates generated by CFSSL.
439+
*
440+
* CFSSL does not add Authority Key Identifier (AKI) to self-signed root certificates.
441+
*/
442+
if (!$isSelfSigned && !isset($parsed['extensions']['authorityKeyIdentifier'])) {
443+
$missingExtensions[] = 'Authority Key Identifier (AKI)';
444+
}
445+
446+
if (!isset($parsed['extensions']['crlDistributionPoints'])) {
447+
$missingExtensions[] = 'CRL Distribution Points';
448+
}
449+
450+
if (!empty($missingExtensions)) {
451+
$extensionsList = implode(', ', $missingExtensions);
452+
$minorIssues[] = "Missing modern extensions: {$extensionsList}";
453+
}
454+
455+
if (!empty($criticalIssues)) {
456+
$issuesList = implode(', ', $criticalIssues);
457+
return (new ConfigureCheckHelper())
458+
->setErrorMessage("Root certificate has critical issues: {$issuesList}")
459+
->setResource($this->getConfigureCheckResourceName())
460+
->setTip($this->getCertificateRegenerationTip());
461+
}
462+
463+
if (!empty($minorIssues)) {
464+
$issuesList = implode(', ', $minorIssues);
465+
return (new ConfigureCheckHelper())
466+
->setInfoMessage("Root certificate could benefit from modern features: {$issuesList}")
467+
->setResource($this->getConfigureCheckResourceName())
468+
->setTip($this->getCertificateRegenerationTip() . ' (recommended but not required)');
469+
}
470+
471+
return null;
472+
473+
} catch (\Exception $e) {
474+
return (new ConfigureCheckHelper())
475+
->setErrorMessage('Failed to analyze root certificate: ' . $e->getMessage())
476+
->setResource($this->getConfigureCheckResourceName())
477+
->setTip('Check if the root certificate file is valid');
478+
}
479+
}
480+
357481
public function toArray(): array {
358482
$return = [
359483
'configPath' => $this->getConfigPath(),

lib/Handler/CertificateEngine/CfsslHandler.php

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -109,24 +109,28 @@ public function isSetupOk(): bool {
109109
return false;
110110
}
111111

112-
public function configureCheck(): array {
113-
$return = $this->checkBinaries();
114-
$configPath = $this->getConfigPath();
115-
if (is_dir($configPath)) {
116-
return array_merge(
117-
$return,
118-
[(new ConfigureCheckHelper())
119-
->setSuccessMessage('Root certificate config files found.')
120-
->setResource('cfssl-configure')]
121-
);
122-
}
123-
return array_merge(
124-
$return,
125-
[(new ConfigureCheckHelper())
126-
->setErrorMessage('CFSSL (root certificate) not configured.')
127-
->setResource('cfssl-configure')
128-
->setTip('Run occ libresign:configure:cfssl --help')]
129-
);
112+
protected function getConfigureCheckResourceName(): string {
113+
return 'cfssl-configure';
114+
}
115+
116+
protected function getCertificateRegenerationTip(): string {
117+
return 'Consider regenerating the root certificate with: occ libresign:configure:cfssl --cn="Your CA Name"';
118+
}
119+
120+
protected function getEngineSpecificChecks(): array {
121+
return $this->checkBinaries();
122+
}
123+
124+
protected function getSetupSuccessMessage(): string {
125+
return 'Root certificate config files found.';
126+
}
127+
128+
protected function getSetupErrorMessage(): string {
129+
return 'CFSSL (root certificate) not configured.';
130+
}
131+
132+
protected function getSetupErrorTip(): string {
133+
return 'Run occ libresign:configure:cfssl --help';
130134
}
131135

132136
public function toArray(): array {
@@ -447,7 +451,6 @@ private function checkBinaries(): array {
447451
return $return;
448452
}
449453

450-
#[\Override]
451454
public function generateCrlDer(array $revokedCertificates): string {
452455
try {
453456
$queryParams = [];

lib/Handler/CertificateEngine/NoneHandler.php

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,30 @@
99
namespace OCA\Libresign\Handler\CertificateEngine;
1010

1111
class NoneHandler extends AEngineHandler implements IEngineHandler {
12+
protected function getConfigureCheckResourceName(): string {
13+
return 'none-configure';
14+
}
15+
16+
protected function getCertificateRegenerationTip(): string {
17+
return 'Switch to a proper certificate engine: occ libresign:configure:openssl or occ libresign:configure:cfssl';
18+
}
19+
20+
protected function getEngineSpecificChecks(): array {
21+
return [];
22+
}
23+
24+
protected function getSetupSuccessMessage(): string {
25+
return 'None handler is active (no certificates required).';
26+
}
27+
28+
protected function getSetupErrorMessage(): string {
29+
return 'None handler configuration error.';
30+
}
31+
32+
protected function getSetupErrorTip(): string {
33+
return 'Switch to a proper certificate engine: occ libresign:configure:openssl or occ libresign:configure:cfssl';
34+
}
35+
1236
public function generateRootCert(
1337
string $commonName,
1438
array $names = [],
@@ -23,11 +47,6 @@ public function isSetupOk(): bool {
2347
return true;
2448
}
2549

26-
public function configureCheck(): array {
27-
return [];
28-
}
29-
30-
#[\Override]
3150
public function generateCrlDer(array $revokedCertificates): string {
3251
throw new \RuntimeException('CRL generation is not supported by None handler');
3352
}

lib/Handler/CertificateEngine/OpenSslHandler.php

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -331,16 +331,28 @@ public function isSetupOk(): bool {
331331
return $certificate && $privateKey;
332332
}
333333

334-
public function configureCheck(): array {
335-
if ($this->isSetupOk()) {
336-
return [(new ConfigureCheckHelper())
337-
->setSuccessMessage('Root certificate setup is working fine.')
338-
->setResource('openssl-configure')];
339-
}
340-
return [(new ConfigureCheckHelper())
341-
->setErrorMessage('OpenSSL (root certificate) not configured.')
342-
->setResource('openssl-configure')
343-
->setTip('Run occ libresign:configure:openssl --help')];
334+
protected function getConfigureCheckResourceName(): string {
335+
return 'openssl-configure';
336+
}
337+
338+
protected function getCertificateRegenerationTip(): string {
339+
return 'Consider regenerating the root certificate with: occ libresign:configure:openssl --cn="Your CA Name"';
340+
}
341+
342+
protected function getEngineSpecificChecks(): array {
343+
return [];
344+
}
345+
346+
protected function getSetupSuccessMessage(): string {
347+
return 'Root certificate setup is working fine.';
348+
}
349+
350+
protected function getSetupErrorMessage(): string {
351+
return 'OpenSSL (root certificate) not configured.';
352+
}
353+
354+
protected function getSetupErrorTip(): string {
355+
return 'Run occ libresign:configure:openssl --help';
344356
}
345357

346358
#[\Override]

0 commit comments

Comments
 (0)