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') }}
@@ -38,17 +46,18 @@
+ @click="handleModal('resetPassword')">
{{ t('librsign', 'Change password') }}
-
-
-
+
+
+
+
@@ -72,10 +81,12 @@ import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'
import { showError, showSuccess } from '@nextcloud/dialogs'
import CloudUploadIcon from 'vue-material-design-icons/CloudUpload.vue'
+import LockOpenCheckIcon from 'vue-material-design-icons/LockOpenCheck.vue'
import DeleteIcon from 'vue-material-design-icons/Delete.vue'
import FileReplaceIcon from 'vue-material-design-icons/FileReplace.vue'
import CertificateIcon from 'vue-material-design-icons/Certificate.vue'
import CreatePassword from '../CreatePassword.vue'
+import ReadCertificate from '../ReadCertificate.vue'
import ResetPassword from '../ResetPassword.vue'
import UserImage from './partials/UserImage.vue'
import Signatures from './partials/Signatures.vue'
@@ -90,10 +101,12 @@ export default {
NcContent,
NcButton,
CloudUploadIcon,
+ LockOpenCheckIcon,
DeleteIcon,
FileReplaceIcon,
CertificateIcon,
CreatePassword,
+ ReadCertificate,
ResetPassword,
Signatures,
UserImage,
@@ -107,7 +120,7 @@ export default {
data() {
return {
user: getCurrentUser(),
- modal: false,
+ modal: '',
certificateEngine: loadState('libresign', 'certificate_engine', ''),
}
},
diff --git a/src/views/CreatePassword.vue b/src/views/CreatePassword.vue
index 57d8b4124f..82d48a774e 100644
--- a/src/views/CreatePassword.vue
+++ b/src/views/CreatePassword.vue
@@ -49,10 +49,8 @@ export default {
},
data() {
return {
- modal: false,
hasLoading: false,
password: '',
- hasPfx: false,
}
},
methods: {
@@ -64,7 +62,7 @@ export default {
.then(() => {
showSuccess(t('libresign', 'New password to sign documents has been created'))
this.signMethodsStore.setHasSignatureFile(true)
- this.clear()
+ this.password = ''
this.$emit('close', true)
this.$emit('password:created', true)
})
@@ -79,9 +77,6 @@ export default {
})
this.hasLoading = false
},
- clear() {
- this.password = ''
- },
},
}
diff --git a/src/views/ReadCertificate.vue b/src/views/ReadCertificate.vue
new file mode 100644
index 0000000000..5368b216f0
--- /dev/null
+++ b/src/views/ReadCertificate.vue
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+