diff --git a/appinfo/routes/routesAccountController.php b/appinfo/routes/routesAccountController.php index 7c2c1da0c2..641f80566b 100644 --- a/appinfo/routes/routesAccountController.php +++ b/appinfo/routes/routesAccountController.php @@ -9,6 +9,7 @@ ['name' => 'account#createToSign', 'url' => '/api/{apiVersion}/account/create/{uuid}', 'verb' => 'POST', 'requirements' => $requirements], ['name' => 'account#me', 'url' => '/api/{apiVersion}/account/me', 'verb' => 'GET', 'requirements' => $requirements], ['name' => 'account#uploadPfx', 'url' => '/api/{apiVersion}/account/pfx', 'verb' => 'POST', 'requirements' => $requirements], + ['name' => 'account#readPfxData', 'url' => '/api/{apiVersion}/account/pfx/read', 'verb' => 'POST', 'requirements' => $requirements], ['name' => 'account#updatePfxPassword', 'url' => '/api/{apiVersion}/account/pfx', 'verb' => 'PATCH', 'requirements' => $requirements], ['name' => 'account#deletePfx', 'url' => '/api/{apiVersion}/account/pfx', 'verb' => 'DELETE', 'requirements' => $requirements], ['name' => 'account#updateSettings', 'url' => '/api/{apiVersion}/account/settings', 'verb' => 'PATCH', 'requirements' => $requirements], diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php index e233b85993..419eb34547 100644 --- a/lib/Controller/AccountController.php +++ b/lib/Controller/AccountController.php @@ -538,4 +538,23 @@ public function updatePfxPassword($current, $new): JSONResponse { Http::STATUS_ACCEPTED ); } + + #[NoAdminRequired] + #[NoCSRFRequired] + public function readPfxData(string $password): JSONResponse { + try { + $data = $this->accountService->readPfxData($this->userSession->getUser(), $password); + } catch (LibresignException $e) { + return new JSONResponse( + [ + 'message' => $e->getMessage() + ], + Http::STATUS_BAD_REQUEST + ); + } + return new JSONResponse( + $data, + Http::STATUS_ACCEPTED + ); + } } diff --git a/lib/Handler/CertificateEngine/AEngineHandler.php b/lib/Handler/CertificateEngine/AEngineHandler.php index c3061c74c7..9aa69d8f32 100644 --- a/lib/Handler/CertificateEngine/AEngineHandler.php +++ b/lib/Handler/CertificateEngine/AEngineHandler.php @@ -33,6 +33,7 @@ use OCP\Files\IAppData; use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IConfig; +use OCP\IDateTimeFormatter; use ReflectionClass; /** @@ -76,6 +77,7 @@ public function __construct( protected IConfig $config, protected IAppConfig $appConfig, protected IAppDataFactory $appDataFactory, + protected IDateTimeFormatter $dateTimeFormatter, ) { $this->appData = $appDataFactory->get('libresign'); } @@ -116,6 +118,31 @@ public function updatePassword(string $certificate, string $currentPrivateKey, s return $certContent; } + public function readCertificate(string $certificate, string $privateKey): array { + if (empty($certificate) || empty($privateKey)) { + throw new EmptyRootCertificateException(); + } + openssl_pkcs12_read($certificate, $certContent, $privateKey); + if (empty($certContent)) { + throw new InvalidPasswordException(); + } + $parsed = openssl_x509_parse(openssl_x509_read($certContent['cert'])); + + $return['name'] = $parsed['name']; + $return['subject'] = $parsed['subject']; + if (is_array($return['subject']['OU']) && !empty($return['subject']['OU'])) { + $return['subject']['OU'] = implode(', ', $return['subject']['OU']); + } + $return['subjectAltName'] = $parsed['extensions']['subjectAltName']; + $return['issuer'] = $parsed['issuer']; + $return['issuerInfoAccess'] = $parsed['extensions']['authorityInfoAccess']; + $return['validate'] = [ + 'from' => $this->dateTimeFormatter->formatDateTime($parsed['validFrom_time_t']), + 'to' => $this->dateTimeFormatter->formatDateTime($parsed['validTo_time_t']), + ]; + return $return; + } + public function translateToLong($name): string { switch ($name) { case 'CN': diff --git a/lib/Handler/CertificateEngine/CfsslHandler.php b/lib/Handler/CertificateEngine/CfsslHandler.php index 5d4dff3e3e..5e9cf44881 100644 --- a/lib/Handler/CertificateEngine/CfsslHandler.php +++ b/lib/Handler/CertificateEngine/CfsslHandler.php @@ -36,6 +36,7 @@ use OCP\AppFramework\Services\IAppConfig; use OCP\Files\AppData\IAppDataFactory; use OCP\IConfig; +use OCP\IDateTimeFormatter; /** * Class CfsslHandler @@ -58,8 +59,9 @@ public function __construct( private SystemConfig $systemConfig, private CfsslServerHandler $cfsslServerHandler, protected IAppDataFactory $appDataFactory, + protected IDateTimeFormatter $dateTimeFormatter, ) { - parent::__construct($config, $appConfig, $appDataFactory); + parent::__construct($config, $appConfig, $appDataFactory, $dateTimeFormatter); } private function getClient(): Client { diff --git a/lib/Handler/Pkcs12Handler.php b/lib/Handler/Pkcs12Handler.php index 8f6524f7c3..cf51efc16b 100644 --- a/lib/Handler/Pkcs12Handler.php +++ b/lib/Handler/Pkcs12Handler.php @@ -99,6 +99,14 @@ public function updatePassword(string $uid, string $currentPrivateKey, string $n return $this->savePfx($uid, $content); } + public function readCertificate(string $uid, string $privateKey): array { + $pfx = $this->getPfx($uid); + return $this->certificateEngineHandler->getEngine()->readCertificate( + $pfx, + $privateKey + ); + } + /** * Get content of pfx file */ diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index 4ee1f0bb80..4768fb327c 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -522,4 +522,15 @@ public function updatePfxPassword(IUser $user, string $current, string $new): vo throw new LibresignException($this->l10n->t('Invalid user or password')); } } + + /** + * @throws LibresignException when have not a certificate file + */ + public function readPfxData(IUser $user, string $password): array { + try { + return $this->pkcs12Handler->readCertificate($user->getUID(), $password); + } catch (InvalidPasswordException $e) { + throw new LibresignException($this->l10n->t('Invalid user or password')); + } + } } diff --git a/src/helpers/certification.js b/src/helpers/certification.js index 2baae4db9b..868a1d5b54 100644 --- a/src/helpers/certification.js +++ b/src/helpers/certification.js @@ -19,6 +19,13 @@ export const options = [ value: '', helperText: t('libresign', 'Two-letter ISO 3166 country code'), }, + { + id: 'CN', + label: 'Name', + min: 1, + value: '', + helperText: t('libresign', 'Name (CN)'), + }, { id: 'ST', label: 'State', diff --git a/src/views/Account/Account.vue b/src/views/Account/Account.vue index a91e6db8ff..40e04cfc7d 100644 --- a/src/views/Account/Account.vue +++ b/src/views/Account/Account.vue @@ -20,6 +20,14 @@ + + {{ t('libresign', 'Read certificate') }} + + @@ -30,7 +38,7 @@ + @click="handleModal('createPassword')"> {{ t('libresign', 'Create certificate') }}