Skip to content

Commit

Permalink
Merge pull request #2719 from LibreSign/backport/2717/stable29
Browse files Browse the repository at this point in the history
[stable29] fix: Read legacy certificate
  • Loading branch information
vitormattos authored Apr 12, 2024
2 parents 5a7f259 + a26150c commit defd941
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 13 deletions.
47 changes: 39 additions & 8 deletions lib/Handler/CertificateEngine/AEngineHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use OCP\Files\SimpleFS\ISimpleFolder;
use OCP\IConfig;
use OCP\IDateTimeFormatter;
use OCP\ITempManager;
use OpenSSLAsymmetricKey;
use OpenSSLCertificate;
use ReflectionClass;
Expand Down Expand Up @@ -80,6 +81,7 @@ public function __construct(
protected IAppConfig $appConfig,
protected IAppDataFactory $appDataFactory,
protected IDateTimeFormatter $dateTimeFormatter,
protected ITempManager $tempManager,
) {
$this->appData = $appDataFactory->get('libresign');
}
Expand Down Expand Up @@ -114,10 +116,7 @@ public function updatePassword(string $certificate, string $currentPrivateKey, s
if (empty($certificate) || empty($currentPrivateKey) || empty($newPrivateKey)) {
throw new EmptyCertificateException();
}
openssl_pkcs12_read($certificate, $certContent, $currentPrivateKey);
if (empty($certContent)) {
throw new InvalidPasswordException();
}
$certContent = $this->opensslPkcs12Read($certificate, $currentPrivateKey);
$this->setPassword($newPrivateKey);
$certContent = self::exportToPkcs12($certContent['cert'], $certContent['pkey']);
return $certContent;
Expand All @@ -127,10 +126,7 @@ public function readCertificate(string $certificate, string $privateKey): array
if (empty($certificate) || empty($privateKey)) {
throw new EmptyCertificateException();
}
openssl_pkcs12_read($certificate, $certContent, $privateKey);
if (empty($certContent)) {
throw new InvalidPasswordException();
}
$certContent = $this->opensslPkcs12Read($certificate, $privateKey);
$parsed = openssl_x509_parse(openssl_x509_read($certContent['cert']));

$return['name'] = $parsed['name'];
Expand All @@ -144,6 +140,41 @@ public function readCertificate(string $certificate, string $privateKey): array
return $return;
}

public function opensslPkcs12Read(string &$certificate, string $privateKey): array {
openssl_pkcs12_read($certificate, $certContent, $privateKey);
if (!empty($certContent)) {
return $certContent;
}
/**
* Reference:
*
* https://github.com/php/php-src/issues/12128
* https://www.php.net/manual/en/function.openssl-pkcs12-read.php#128992
*/
$msg = openssl_error_string();
if ($msg === 'error:0308010C:digital envelope routines::unsupported') {
$tempPassword = $this->tempManager->getTemporaryFile();
$tempEncriptedOriginal = $this->tempManager->getTemporaryFile();
$tempEncriptedRepacked = $this->tempManager->getTemporaryFile();
$tempDecrypted = $this->tempManager->getTemporaryFile();
file_put_contents($tempPassword, $privateKey);
file_put_contents($tempEncriptedOriginal, $certificate);
shell_exec(<<<REPACK_COMMAND
cat $tempPassword | openssl pkcs12 -legacy -in $tempEncriptedOriginal -nodes -out $tempDecrypted -passin stdin &&
cat $tempPassword | openssl pkcs12 -in $tempDecrypted -export -out $tempEncriptedRepacked -passout stdin
REPACK_COMMAND
);
$certificateRepacked = file_get_contents($tempEncriptedRepacked);
$this->tempManager->clean();
openssl_pkcs12_read($certificateRepacked, $certContent, $privateKey);
if (!empty($certContent)) {
$certificate = $certificateRepacked;
return $certContent;
}
}
throw new InvalidPasswordException();
}

public function translateToLong($name): string {
switch ($name) {
case 'CN':
Expand Down
4 changes: 3 additions & 1 deletion lib/Handler/CertificateEngine/CfsslHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
use OCP\Files\AppData\IAppDataFactory;
use OCP\IConfig;
use OCP\IDateTimeFormatter;
use OCP\ITempManager;

/**
* Class CfsslHandler
Expand All @@ -60,8 +61,9 @@ public function __construct(
private CfsslServerHandler $cfsslServerHandler,
protected IAppDataFactory $appDataFactory,
protected IDateTimeFormatter $dateTimeFormatter,
protected ITempManager $tempManager,
) {
parent::__construct($config, $appConfig, $appDataFactory, $dateTimeFormatter);
parent::__construct($config, $appConfig, $appDataFactory, $dateTimeFormatter, $tempManager);
}

public function generateRootCert(
Expand Down
2 changes: 1 addition & 1 deletion lib/Handler/CertificateEngine/OpenSslHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function __construct(
protected IDateTimeFormatter $dateTimeFormatter,
protected ITempManager $tempManager,
) {
parent::__construct($config, $appConfig, $appDataFactory, $dateTimeFormatter);
parent::__construct($config, $appConfig, $appDataFactory, $dateTimeFormatter, $tempManager);
}

public function generateRootCert(
Expand Down
4 changes: 4 additions & 0 deletions lib/Handler/Pkcs12Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public function updatePassword(string $uid, string $currentPrivateKey, string $n
}

public function readCertificate(string $uid, string $privateKey): array {
$this->setPassword($privateKey);
$pfx = $this->getPfx($uid);
return $this->certificateEngineHandler->getEngine()->readCertificate(
$pfx,
Expand Down Expand Up @@ -132,6 +133,9 @@ public function getPfx(?string $uid = null): string {
if (empty($this->pfxContent)) {
throw new LibresignException($this->l10n->t('Password to sign not defined. Create a password to sign.'), 400);
}
if ($this->getPassword()) {
$this->certificateEngineHandler->getEngine()->opensslPkcs12Read($this->pfxContent, $this->getPassword());
}
return $this->pfxContent;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Handler/SignEngineHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ abstract class SignEngineHandler implements ISignEngineHandler {
private $inputFile;
private string $certificate;
/** @var string */
private $password;
private $password = '';
/** @var VisibleElementAssoc[] */
private $visibleElements = [];

Expand Down
4 changes: 2 additions & 2 deletions lib/Service/IdentifyMethod/SignatureMethod/Password.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ public function __construct(
}

public function validateToIdentify(): void {
$this->pkcs12Handler->setPassword($this->codeSentByUser);
$pfx = $this->pkcs12Handler->getPfx($this->userSession->getUser()?->getUID());
openssl_pkcs12_read($pfx, $cert_info, $this->codeSentByUser);
if (empty($cert_info)) {
if (empty($pfx)) {
throw new LibresignException($this->identifyService->getL10n()->t('Invalid password'));
}
}
Expand Down

0 comments on commit defd941

Please sign in to comment.